home *** CD-ROM | disk | FTP | other *** search
/ Enter 2001 August / EnterCD8.iso / Internet / HTTrack Website Copier / httrack.exe / {app} / src / httrack.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-06-03  |  131.6 KB  |  3,706 lines

  1. /* ------------------------------------------------------------ */
  2. /*
  3. HTTrack Website Copier, Offline Browser for Windows and Unix
  4. Copyright (C) Xavier Roche and other contributors
  5.  
  6. This program is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 2
  9. of the License, or any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  19.  
  20.  
  21. Important notes:
  22.  
  23. - We hereby ask people using this source NOT to use it in purpose of grabbing
  24. emails addresses, or collecting any other private information on persons.
  25. This would disgrace our work, and spoil the many hours we spent on it.
  26.  
  27.  
  28. Please visit our Website: http://www.httrack.com
  29. */
  30.  
  31.  
  32. /* ------------------------------------------------------------ */
  33. /* File: Main source                                            */
  34. /* Author: Xavier Roche                                         */
  35. /* ------------------------------------------------------------ */
  36.  
  37. #include "httrack.h"
  38.  
  39. /* specific definitions */
  40. #include "htsbase.h"
  41. #include "htsnet.h"
  42. #include "htsbauth.h"
  43. #include "htsmd5.h"
  44. #include "htsindex.h"
  45. #include <stdio.h>
  46. #include <stdlib.h>
  47. #include <string.h>
  48. #include <time.h>
  49. #include <fcntl.h>
  50. #include <ctype.h>
  51. /* END specific definitions */
  52.  
  53.  
  54. /* HTML parsing */
  55. #if HTS_ANALYSTE==2
  56. char _hts_errmsg[1100]="";
  57. int _hts_in_html_parsing=0;
  58. int _hts_in_html_done=0;  // % done
  59. int _hts_in_html_poll=0;  // parsing
  60. int _hts_setpause=0;
  61. httrackp* _hts_setopt=NULL;
  62. char** _hts_addurl=NULL;
  63. //
  64. int _hts_cancel=0;
  65. #endif
  66.  
  67.  
  68.  
  69. char* structcheck_buff=NULL;
  70. int exit_xh;          /* quick exit (fatal error or interrupt) */
  71.  
  72. /* debug */
  73. #if DEBUG_SHOWTYPES
  74. char REG[32768]="\n";
  75. #endif
  76. #if NSDEBUG
  77. int nsocDEBUG=0;
  78. #endif
  79.  
  80. //
  81. #define _CLRSCR printf("\33[m\33[2J");
  82. #define _GOTOXY(X,Y) printf("\33[" X ";" Y "f");
  83.  
  84. #if DEBUG_CHECKINT
  85.  #define _CHECKINT_FAIL(a) printf("\n%s\n",a); fflush(stdout); exit(1);
  86.  #define _CHECKINT(obj_ptr,message) \
  87.    if (obj_ptr) {\
  88.      if (( * ((char*) (obj_ptr)) != 0) || ( * ((char*) (((char*) (obj_ptr)) + sizeof(*(obj_ptr))-1)) != 0)) {\
  89.        char msg[1100];\
  90.        if (( * ((char*) (obj_ptr)) != 0) && ( * ((char*) (((char*) (obj_ptr)) + sizeof(*(obj_ptr))-1)) != 0))\
  91.          sprintf(msg,"* PANIC: Integrity error (structure crushed)  in: %s",message);\
  92.        else if ( * ((char*) (obj_ptr)) != 0)\
  93.          sprintf(msg,"* PANIC: Integrity error (start of structure) in: %s",message);\
  94.        else\
  95.          sprintf(msg,"* PANIC: Integrity error (end of structure)   in: %s",message);\
  96.        _CHECKINT_FAIL(msg);\
  97.      }\
  98.    } else {\
  99.      char msg[1100];\
  100.      sprintf(msg,"* PANIC: NULL pointer in: %s",message);\
  101.      _CHECKINT_FAIL(msg);\
  102.    }
  103. #endif
  104.  
  105. #if DEBUG_HASH
  106.   // longest hash chain?
  107.   int longest_hash[3]={0,0,0},hashnumber=0;
  108. #endif
  109.  
  110. // demande d'interaction avec le shell
  111. #if HTS_ANALYSTE==2
  112. char HTbuff[1100];
  113. #endif
  114.  
  115.  
  116.  
  117. // DΘbut de httpmirror, routines annexes
  118.  
  119. // version 1 pour httpmirror
  120. // flusher si on doit lire peu α peu le fichier
  121. #define test_flush if (opt.flush) { fflush(opt.log); fflush(opt.errlog); }
  122.  
  123. // pour allΘger la syntaxe, des raccourcis sont crΘΘs
  124. #define urladr   (liens[ptr]->adr)
  125. #define urlfil   (liens[ptr]->fil)
  126. #define savename (liens[ptr]->sav)
  127. //#define level    (liens[ptr]->depth)
  128. #define new_stat_bytes (HTS_STAT.HTS_TOTAL_RECV)
  129.  
  130. // au cas o∙ nous devons quitter rapidement xhttpmirror (plus de mΘmoire, etc)
  131. // note: partir de liens_max.. vers 0.. sinon erreur de violation de mΘmoire: les liens suivants
  132. // ne sont plus α nous.. agh! [dur celui-lα]
  133. #if HTS_ANALYSTE
  134.  #define HTMLCHECK_UNINIT hts_htmlcheck_end();
  135. #else
  136. #define HTMLCHECK_UNINIT 
  137. #endif
  138.  
  139. #define XH_extuninit { \
  140.   int i; \
  141.   HTMLCHECK_UNINIT \
  142.   if (liens!=NULL) { \
  143.   for(i=lien_max-1;i>0;i--) { \
  144.   if (liens[i]) { \
  145.   if (liens[i]->firstblock==1) { \
  146.   freet(liens[i]); \
  147.   liens[i]=NULL; \
  148.   } \
  149.   } \
  150.   } \
  151.   liens=NULL; \
  152.   } \
  153.   if (filters[0]) { \
  154.   freet(filters[0]); filters[0]=NULL; \
  155.   } \
  156.   if (back) { \
  157.   int i; \
  158.   for(i=0;i<back_max;i++) { \
  159.   back_delete(back,i); \
  160.   } \
  161.   freet(back); back=NULL;  \
  162.   } \
  163.   checkrobots_free(&robots);\
  164.   if (cache.use) { freet(cache.use); cache.use=NULL; } \
  165.   if (cache.dat) { fclose(cache.dat); cache.dat=NULL; }  \
  166.   if (cache.ndx) { fclose(cache.ndx); cache.ndx=NULL; } \
  167.   if (cache.olddat) { fclose(cache.olddat); cache.olddat=NULL; } \
  168.   if (cache.lst) { fclose(cache.lst); cache.lst=NULL; } \
  169.   if (opt.log) fflush(opt.log); \
  170.   if (opt.errlog) fflush(opt.errlog);\
  171.   if (makestat_fp) { fclose(makestat_fp); makestat_fp=NULL; } \
  172.   if (maketrack_fp){ fclose(maketrack_fp); maketrack_fp=NULL; } \
  173.   if (opt.accept_cookie) cookie_save(opt.cookie,fconcat(opt.path_log,"cookies.txt")); \
  174.   if (makeindex_fp) { fclose(makeindex_fp); makeindex_fp=NULL; } \
  175.   if (cache_hash) { inthash_del(cache_hash,cache_hash_size); cache_hash=NULL; } \
  176. }
  177. #define XH_uninit XH_extuninit if (r.adr) { freet(r.adr); r.adr=NULL; } 
  178.  
  179. // Enregistrement d'un lien:
  180. // on calcule la taille nΘcessaire: taille des 3 chaεnes α stocker (taille forcΘe paire, plus 2 octets de sΘcuritΘ)
  181. // puis on vΘrifie qu'on a assez de marge dans le buffer - sinon on en rΘalloue un autre
  182. // enfin on Θcrit α l'adresse courante du buffer, qu'on incrΘmente. on dΘcrΘmente la taille dispo d'autant ensuite
  183. // codebase: si non nul et si .class stockee on le note pour chemin primaire pour classes
  184. // FA,FS: former_adr et former_fil, lien original
  185. #define HTS_ALIGN 4
  186. #if HTS_HASH
  187. #define liens_record_sav_len(A) 
  188. #else
  189. #define liens_record_sav_len(A) (A)->sav_len=strlen((A)->sav)
  190. #endif
  191.  
  192. #define liens_record(A,F,S,FA,FF) { \
  193. int notecode=0; \
  194. int adr_len=strlen(A),fil_len=strlen(F),sav_len=strlen(S),cod_len=0,former_adr_len=strlen(FA),former_fil_len=strlen(FF); \
  195. if (former_adr_len>0) {\
  196. former_adr_len=(former_adr_len/HTS_ALIGN)*HTS_ALIGN+HTS_ALIGN+4; \
  197. former_fil_len=(former_fil_len/HTS_ALIGN)*HTS_ALIGN+HTS_ALIGN+4; \
  198. } else former_adr_len=former_fil_len=0;\
  199. if (strlen(F)>6) if (strnotempty(codebase)) if (strfield(F+strlen(F)-6,".class")) { notecode=1; \
  200. cod_len=strlen(codebase); cod_len=(cod_len/HTS_ALIGN)*HTS_ALIGN+HTS_ALIGN+4; } \
  201. adr_len=(adr_len/HTS_ALIGN)*HTS_ALIGN+HTS_ALIGN+4; fil_len=(fil_len/HTS_ALIGN)*HTS_ALIGN+HTS_ALIGN+4; sav_len=(sav_len/HTS_ALIGN)*HTS_ALIGN+HTS_ALIGN+4; \
  202. if ((int) lien_size < (int) (adr_len+fil_len+sav_len+cod_len+former_adr_len+former_fil_len+sizeof(lien_url))) { \
  203. lien_buffer=(char*) ((void*) calloct(add_tab_alloc,1)); \
  204. lien_size=add_tab_alloc; \
  205. if (lien_buffer!=NULL) { \
  206. liens[lien_tot]=(lien_url*) (void*) lien_buffer; lien_buffer+=sizeof(lien_url); lien_size-=sizeof(lien_url); \
  207. liens[lien_tot]->firstblock=1; \
  208. } \
  209. } else { \
  210. liens[lien_tot]=(lien_url*) (void*) lien_buffer; lien_buffer+=sizeof(lien_url); lien_size-=sizeof(lien_url); \
  211. liens[lien_tot]->firstblock=0; \
  212. } \
  213. if (liens[lien_tot]!=NULL) { \
  214. liens[lien_tot]->adr=lien_buffer; lien_buffer+=adr_len; lien_size-=adr_len; \
  215. liens[lien_tot]->fil=lien_buffer; lien_buffer+=fil_len; lien_size-=fil_len; \
  216. liens[lien_tot]->sav=lien_buffer; lien_buffer+=sav_len; lien_size-=sav_len; \
  217. liens[lien_tot]->cod=NULL; \
  218. if (notecode) { liens[lien_tot]->cod=lien_buffer; lien_buffer+=cod_len; lien_size-=cod_len; strcpy(liens[lien_tot]->cod,codebase); } \
  219. if (former_adr_len>0) {\
  220. liens[lien_tot]->former_adr=lien_buffer; lien_buffer+=former_adr_len; lien_size-=former_adr_len; \
  221. liens[lien_tot]->former_fil=lien_buffer; lien_buffer+=former_fil_len; lien_size-=former_fil_len; \
  222. strcpy(liens[lien_tot]->former_adr,FA); \
  223. strcpy(liens[lien_tot]->former_fil,FF); \
  224. }\
  225. strcpy(liens[lien_tot]->adr,A); \
  226. strcpy(liens[lien_tot]->fil,F); \
  227. strcpy(liens[lien_tot]->sav,S); \
  228. liens_record_sav_len(liens[lien_tot]); \
  229. hash_write(&hash,lien_tot);  \
  230. } \
  231. }
  232.  
  233. /* - abandonnΘ (simplifie) -
  234. // Ajouter α un lien EXISTANT deux champs former_adr et former_fil pour indiquer le nom d'un fichier avant un "move"
  235. // NOTE: si un alloc est fait ici il n'y aura pas de freet() α la fin, tant pis (firstbloc)
  236. #define liens_add_former(index,A,F) { \
  237. int adr_len=strlen(A),fil_len=strlen(F); \
  238. adr_len=(adr_len/HTS_ALIGN)*HTS_ALIGN+HTS_ALIGN+4; fil_len=(fil_len/HTS_ALIGN)*HTS_ALIGN+HTS_ALIGN+4; \
  239. if ((int) lien_size < (int) (adr_len+fil_len)) { \
  240. lien_buffer=(char*) calloct(add_tab_alloc,1); \
  241. lien_size=add_tab_alloc; \
  242. } \
  243. if (lien_buffer!=NULL) { \
  244. if (liens[lien_tot]!=NULL) { \
  245. liens[lien_tot]->former_adr=lien_buffer; lien_buffer+=adr_len; lien_size-=adr_len; \
  246. liens[lien_tot]->former_fil=lien_buffer; lien_buffer+=fil_len; lien_size-=fil_len; \
  247. strcpy(liens[lien_tot]->former_adr,A); \
  248. strcpy(liens[lien_tot]->former_fil,F); \
  249. } \
  250. } \
  251. }
  252. */
  253.  
  254. #if 0
  255. #define HT_ADD_ADR { \
  256.   fwrite(lastsaved,1,((int) adr)- ((int) lastsaved),fp); \
  257.   lastsaved=adr; }
  258. #define HT_ADD(A) fwrite(A,1,(int) strlen(A),fp);
  259. #define HT_ADD_START
  260. #define HT_ADD_END if (fp) { fclose(fp); fp=NULL; }
  261. #define HT_ADD_FOP { \
  262.   fp=filecreate(savename); \
  263.   if (fp==NULL) { \
  264.   if (opt.errlog) { \
  265.   fspc(opt.errlog,"error"); fprintf(opt.errlog,"Unable to create %s for %s%s"LF,savename,urladr,urlfil); \
  266.   test_flush; \
  267.   } \
  268.   freet(r.adr); r.adr=NULL; \
  269.   error=1; \
  270.   } \
  271.   }
  272. #else
  273. // version optimisΘe, qui permet de ne pas toucher aux html non modifiΘs (update)
  274. #define HT_ADD_CHK(A) if (((int) A+ht_len+1)>ht_size) { \
  275.   ht_size=A+ht_len+8192; \
  276.   ht_buff=(char*) realloct(ht_buff,ht_size); \
  277.   if (ht_buff==NULL) { \
  278.   printf("PANIC! : Not enough memory [%d]\n",__LINE__); \
  279.   XH_uninit; \
  280.   } \
  281.   } \
  282.   ht_len+=A;
  283. #define HT_ADD_ADR { int i,j=ht_len; HT_ADD_CHK(((int) adr)- ((int) lastsaved)) \
  284.   for(i=0;i<((int) adr)- ((int) lastsaved);i++) \
  285.   ht_buff[j+i]=lastsaved[i]; \
  286.   ht_buff[j+((int) adr)- ((int) lastsaved)]='\0'; \
  287.   lastsaved=adr; }
  288. #define HT_ADD(A) { HT_ADD_CHK(strlen(A)) strcat(ht_buff,A); }
  289. #define HT_ADD_START \
  290.   int ht_size=(int)(r.size*5)/4+8192; \
  291.   int ht_len=0; \
  292.   char* ht_buff=NULL; \
  293.   if ((opt.getmode & 1) && (ptr>0)) { \
  294.   ht_buff=(char*) malloct(ht_size); \
  295.   if (ht_buff==NULL) { \
  296.   printf("PANIC! : Not enough memory [%d]\n",__LINE__); \
  297.   XH_uninit; \
  298.   } \
  299.   ht_buff[0]='\0'; \
  300.   }
  301. #define HT_ADD_END { \
  302.   int ok=0;\
  303.   if (ht_buff) { \
  304.   int file_len=(int) strlen(ht_buff);\
  305.   char digest[32+2];\
  306.   digest[0]='\0';\
  307.   domd5mem(ht_buff,file_len,digest,1,0);\
  308.   if (fsize(antislash(savename))==file_len) { \
  309.   int mlen;\
  310.   char* mbuff;\
  311.   cache_readdata(&cache,"//[HTML-MD5]//",savename,&mbuff,&mlen);\
  312.   if (mlen) mbuff[mlen]='\0';\
  313.   if ((mlen == 32) && (strcmp(((mbuff!=NULL)?mbuff:""),digest)==0)) {\
  314.   ok=1;\
  315.   if ( (opt.debug>1) && (opt.log!=NULL) ) {\
  316.   fspc(opt.log,"debug"); fprintf(opt.log,"File not re-written (md5): %s"LF,savename);\
  317.   test_flush;\
  318.   }\
  319.   } else {\
  320.   FILE* fp2; \
  321.   int i=0; \
  322.   fp2=fopen(fconv(savename),"rb"); \
  323.   if (fp2) { \
  324.   ok=1; \
  325.   while((!feof(fp2)) && (ok)) { int c=fgetc(fp2); if (c!=EOF) { if ((char) c!=(char) ht_buff[i++]) ok=0; } } \
  326.   fclose(fp2); \
  327.   } \
  328.   } \
  329.   }\
  330.   if (!ok) { \
  331.   fp=filecreate(savename); \
  332.   if (fp) { \
  333.   if ((int)fwrite(ht_buff,1,file_len,fp) != file_len) { \
  334.   if (opt.errlog) {   \
  335.   fspc(opt.errlog,"error"); fprintf(opt.errlog,"Unable to write HTML file %s"LF,savename);\
  336.   test_flush;\
  337.   }\
  338.   }\
  339.   fclose(fp); fp=NULL; \
  340.   if (strnotempty(r.lastmodified)) \
  341.   set_filetime_rfc822(savename,r.lastmodified); \
  342.   usercommand(0,NULL,antislash(savename)); \
  343.   } else {\
  344.   if (opt.errlog) { \
  345.   fspc(opt.errlog,"error");\
  346.   fprintf(opt.errlog,"Unable to save file %s"LF,savename);\
  347.   test_flush;\
  348.   }\
  349.   }\
  350.   } else filenote(savename,NULL); \
  351.   if (cache.ndx)\
  352.     cache_writedata(cache.ndx,cache.dat,"//[HTML-MD5]//",savename,digest,(int)strlen(digest));\
  353.   } \
  354.   freet(ht_buff); ht_buff=NULL; \
  355.   }
  356. #define HT_ADD_FOP 
  357. #endif
  358.  
  359. // libΘrer filters[0] pour insΘrer un ΘlΘment dans filters[0]
  360. #define HT_INSERT_FILTERS0 {\
  361.   int i;\
  362.   if (filptr>0) {\
  363.     for(i=filptr-1;i>=0;i--) {\
  364.       strcpy(filters[i+1],filters[i]);\
  365.     }\
  366.   }\
  367.   strcpy(filters[0],"");\
  368.   filptr++;\
  369.   filptr=minimum(filptr,filter_max);\
  370. }
  371.  
  372. // DΘbut de httpmirror, robot
  373. // url1 peut Ωtre multiple
  374. int httpmirror(char* url1,httrackp opt) {
  375.   char* primary=NULL;          // premiΦre page, contenant les liens α scanner
  376.   int lien_tot=0;              // nombre de liens pour le moment
  377.   lien_url** liens=NULL;       // les pointeurs sur les liens
  378.   hash_struct hash;            // systΦme de hachage, accΘlΦre la recherche dans les liens
  379.   t_cookie cookie;             // gestion des cookies
  380.   int lien_max=0;
  381.   int lien_size=0;        // octets restants dans buffer liens dispo
  382.   char* lien_buffer=NULL; // buffer liens actuel
  383.   int add_tab_alloc=256000;    // +256K de liens α chaque fois
  384.   //char* tab_alloc=NULL;
  385.   int ptr;             // pointeur actuel sur les liens
  386.   //
  387.   int numero_passe=0;  // deux passes pour html puis images
  388.   int back_max=0;      // fichiers qui peuvent Ωtre en local
  389.   lien_back* back=NULL; // backing en local
  390.   htsblk r;            // retour de certaines fonctions
  391.   double lastime=0;    // pour affichage infos de tmp en tmp
  392.   // pour les stats, nombre de fichiers & octets Θcrits
  393.   LLint stat_fragment=0;  // pour la fragmentation
  394.   //double istat_timestart;   // dΘpart pour calcul instantannΘ
  395.   //
  396.   double last_info_shell=0;
  397.   int info_shell=0;
  398.   // note: α amΘliorer // **
  399.   char* filters[usd_max];
  400.   int filter_max=0;
  401.   int filptr=0;
  402.   //
  403.   int makeindex_done=0;  // lorsque l'index sera fait
  404.   FILE* makeindex_fp=NULL;
  405.   int makeindex_links=0;
  406.   char makeindex_firstlink[HTS_URLMAXSIZE*2];
  407.   // statistiques (mode #Z)
  408.   FILE* makestat_fp=NULL;    // fichier de stats taux transfert
  409.   FILE* maketrack_fp=NULL;   // idem pour le tracking
  410.   double makestat_time=0;    // attente (secondes)
  411.   LLint makestat_total=0;    // repΦre du nombre d'octets transfΘrΘs depuis denriΦre stat
  412.   int makestat_lnk=0;        // idem, pour le nombre de liens
  413.   //
  414.   char codebase[HTS_URLMAXSIZE*2];  // base pour applet java
  415.   char base[HTS_URLMAXSIZE*2];      // base pour les autres fichiers
  416.   //
  417.   cache_back cache;
  418.   robots_wizard robots;    // gestion robots.txt
  419.   hash_chain** cache_hash=NULL;
  420.   int cache_hash_size=0;
  421.   //
  422.   codebase[0]='\0'; base[0]='\0';
  423.   //
  424.   cookie.auth.next=NULL;
  425.   cookie.auth.auth[0]=cookie.auth.prefix[0]='\0';
  426.   //
  427.  
  428.   // noter heure actuelle de dΘpart en secondes
  429.   bzero((char *)&HTS_STAT, sizeof(HTS_STAT));
  430.   HTS_STAT.stat_timestart=time_local();
  431.   //istat_timestart=stat_timestart;
  432.   HTS_STAT.imstat_timestart=mtime_local();
  433.   /* reset stats */
  434.   new_stat_bytes=0;
  435.   HTS_STAT.istat_bytes=0;
  436.   if (opt.aff_progress)
  437.     lastime=HTS_STAT.stat_timestart;
  438.   if (opt.shell) {
  439.     last_info_shell=HTS_STAT.stat_timestart;
  440.   }
  441.   if ((opt.makestat) || (opt.maketrack)){
  442.     makestat_time=HTS_STAT.stat_timestart;
  443.   }
  444.   // initialiser compteur erreurs
  445.   fspc(NULL,NULL);
  446.  
  447.   // initialiser cookie
  448.   if (opt.accept_cookie) {
  449.     opt.cookie=&cookie;
  450.     cookie.max_len=30000;       // max len
  451.     strcpy(cookie.data,"");
  452.     // Charger cookies.txt par dΘfaut ou cookies.txt du miroir
  453.     if (fexist(fconcat(opt.path_log,"cookies.txt")))
  454.       cookie_load(opt.cookie,opt.path_log,"cookies.txt");
  455.     else if (fexist("cookies.txt"))
  456.       cookie_load(opt.cookie,"","cookies.txt");
  457.   } else
  458.     opt.cookie=NULL;
  459.  
  460.   // initialiser exit_xh
  461.   exit_xh=0;          // sortir prΘmaturΘment (var globale)
  462.  
  463.   // initialiser usercommand
  464.   usercommand(opt.sys_com_exec,opt.sys_com,"");
  465.  
  466.   // initialiser verif_backblue
  467.   verif_backblue(NULL);
  468.   verif_external(0,0);
  469.   verif_external(1,0);
  470.  
  471.   // Initialiser indexation
  472.   if (opt.kindex)
  473.     index_init(opt.path_html);
  474.  
  475.   // effacer bloc cache
  476.   bzero((char *)&cache, sizeof(cache_back));
  477.   cache.type=opt.cache;  // cache?
  478.   cache.errlog=opt.errlog;  // err log?
  479.   cache.ptr_ant=cache.ptr_last=0;   // pointeur pour anticiper
  480.  
  481.   // initialiser hash cache
  482.   if (!cache_hash_size) 
  483.     cache_hash_size=HTS_HASH_SIZE;
  484.   cache_hash=(hash_chain**)calloc(cache_hash_size,sizeof(hash_chain*));
  485.   if (cache_hash==NULL) {
  486.     printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  487.     filters[0]=NULL; back_max=0;    // uniquement a cause du warning de XH_extuninit
  488.     XH_extuninit;
  489.     return 0;
  490.   }
  491.   inthash_init(cache_hash,cache_hash_size);
  492.   cache.hash=(void**)cache_hash;      /* copy backcache hash */
  493.   cache.hash_size=cache_hash_size;
  494.  
  495.   // initialiser cache DNS
  496.   _hts_lockdns(-999);
  497.  
  498.   // robots.txt
  499.   strcpy(robots.adr,"!");    // dummy
  500.   robots.token[0]='\0';
  501.   robots.next=NULL;          // suivant
  502.   
  503.   // effacer filters
  504.   filter_max=maximum(opt.maxfilter,128);
  505.   filters[0]=(char*) malloct((filter_max+1)*(HTS_URLMAXSIZE*2));
  506.   if (filters[0]==NULL) {
  507.     printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  508.     back_max=0;    // uniquement a cause du warning de XH_extuninit
  509.     XH_extuninit;
  510.     return 0;
  511.   } else {
  512.     int i;
  513.     for(i=0;i<=filter_max;i++) {    // PLUS UN (sΘcuritΘ)
  514.       filters[i]=filters[0]+i*(HTS_URLMAXSIZE*2);
  515.       filters[i][0]='\0';
  516.     }
  517.   }
  518.   opt.filters.filptr=&filptr;
  519.   opt.filters.filter_max=&filter_max;
  520.   opt.filters.filters=filters;
  521.  
  522.   // tableau de pointeurs sur les liens
  523.   lien_max=maximum(opt.maxlink,32);
  524.   liens=(lien_url**) malloct(lien_max*sizeof(lien_url*));   // tableau de pointeurs sur les liens
  525.   if (liens==NULL) {
  526.     printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  527.     //XH_uninit;
  528.     return 0;
  529.   } else {
  530.     int i;
  531.     for(i=0;i<lien_max;i++) {
  532.       liens[i]=NULL;     
  533.     }
  534.   }
  535.   // initialiser ptr et lien_tot
  536.   ptr=0;
  537.   lien_tot=0;
  538. #if HTS_HASH
  539.   // initialiser hachage
  540.   {
  541.     int i;
  542.     for(i=0;i<HTS_HASH_SIZE;i++)
  543.       hash.hash[0][i]=hash.hash[1][i]=hash.hash[2][i] = -1;    // pas d'entrΘes
  544.     hash.liens = liens;
  545.     hash.max_lien=0;
  546.   }
  547. #endif
  548.  
  549.   
  550.   // copier adresse(s) dans liste des adresses
  551.   {
  552.     char *a=url1;
  553.     int primary_len=8192;
  554.     if (strnotempty(opt.filelist)) {
  555.       primary_len+=max(0,fsize(opt.filelist)*2);
  556.     }
  557.     primary_len+=strlen(url1)*2;
  558.  
  559.     // crΘation de la premiΦre page, qui contient les liens de base α scanner
  560.     // c'est plus propre et plus logique que d'entrer α la main les liens dans la pile
  561.     // on bΘnΘficie ainsi des vΘrifications et des tests du robot pour les liens "primaires"
  562.     primary=(char*) malloct(primary_len); 
  563.     if (primary) {
  564.       primary[0]='\0';
  565.     } else {
  566.       printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  567.       back_max=0;    // uniquement a cause du warning de XH_extuninit
  568.       XH_extuninit;
  569.       return 0;
  570.     }
  571.     
  572.     while(*a) {
  573.       int i;
  574.       int joker=0;
  575.  
  576.       // vΘrifier qu'il n'y a pas de * dans l'url
  577.       if (*a=='+')
  578.         joker=1;
  579.       else if (*a=='-')
  580.         joker=1;
  581.       /* NON, certaines URL ont des * (!)
  582.       else {
  583.         int i=0;
  584.         while((a[i]!=0) && (a[i]!=' ')) if (a[i++]=='*') joker=1;
  585.       }
  586.       */
  587.       
  588.       if (joker) {    // joker ou filters
  589.         //char* p;
  590.         char tempo[HTS_URLMAXSIZE*2];
  591.         int type; int plus=0;
  592.  
  593.         // noter joker (dans b)
  594.         if (*a=='+') {  // champ +
  595.           type=1; plus=1; a++;
  596.         } else if (*a=='-') {  // champ forbidden[]
  597.           type=0; a++;
  598.         } else {  // champ + avec joker sans doute
  599.           type=1;
  600.         }
  601.  
  602.         // recopier prochaine chaine (+ ou -)
  603.         i=0;
  604.         while((*a!=0) && (*a!=' ')) { tempo[i++]=*a; a++; }  
  605.         tempo[i++]='\0';
  606.         while(*a==' ') { a++; }
  607.  
  608.         // sauter les + sans rien aprΦs..
  609.         if (strnotempty(tempo)) {
  610.           if ((plus==0) && (type==1)) {  // implicite: *www.edf.fr par exemple
  611.             if (tempo[strlen(tempo)-1]!='*') {
  612.               strcat(tempo,"*");  // ajouter un *
  613.             }
  614.           }
  615.           if (type)
  616.             strcpy(filters[filptr],"+");
  617.           else
  618.             strcpy(filters[filptr],"-");
  619.           if (strncmp(tempo,"http://",7)==0)
  620.             strcat(filters[filptr],tempo+7);        // ignorer http://
  621.           else if (strncmp(tempo,"ftp://",6)==0)
  622.             strcat(filters[filptr],tempo+6);        // ignorer ftp://
  623.           else
  624.             strcat(filters[filptr],tempo);
  625.           filptr++;          
  626.         }
  627.         
  628.       } else {    // adresse normale
  629.         char url[HTS_URLMAXSIZE*2];
  630.         // prochaine adresse
  631.         i=0;
  632.         while((*a!=0) && (*a!=' ')) { url[i++]=*a; a++; }  
  633.         while(*a==' ') { a++; }
  634.         url[i++]='\0';
  635.  
  636.         strcat(primary,"<PRIMARY=\"");
  637.         if (strstr(url,":/")==NULL)
  638.           strcat(primary,"http://");
  639.         strcat(primary,url);
  640.         strcat(primary,"\">\n");
  641.       }
  642.     }  // while
  643.  
  644.     /* intΘgrer liste de fichiers */
  645.     if (strnotempty(opt.filelist)) {
  646.       FILE* fp=fopen(opt.filelist,"rb");
  647.       if (fp) {
  648.         int n=0;
  649.         char line[512];
  650.         while(!feof(fp)) {
  651.           linput(fp,line,500);
  652.           if (strnotempty(line)) {
  653.             n++;
  654.             strcat(primary,"<PRIMARY=\"");
  655.             if (strstr(line,":/")==NULL)
  656.               strcat(primary,"http://");
  657.             strcat(primary,line);
  658.             strcat(primary,"\">\n");
  659.           }
  660.         }
  661.         fclose(fp);
  662.         if (opt.log!=NULL) {
  663.           fspc(opt.log,"info"); fprintf(opt.log,"%d links added from %s"LF,n,opt.filelist); test_flush;
  664.         }
  665.       } else {
  666.         if (opt.errlog!=NULL) {
  667.           fspc(opt.errlog,"error"); fprintf(opt.errlog,"Could not include URL list: %s"LF,opt.filelist); test_flush;
  668.         }
  669.       }
  670.     }
  671.  
  672.  
  673.     // lien primaire
  674.     liens_record("primary","/primary","primary.html","","");
  675.     if (liens[lien_tot]==NULL) {  // erreur, pas de place rΘservΘe
  676.       printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  677.       if (opt.errlog) {
  678.         fprintf(opt.errlog,"Not enough memory, can not re-allocate %d bytes"LF,(add_tab_alloc+1)*sizeof(lien_url));
  679.         test_flush;
  680.       }
  681.       back_max=0;    // uniquement a cause du warning de XH_extuninit
  682.       XH_extuninit;    // dΘsallocation mΘmoire & buffers
  683.       return 0;
  684.     }    
  685.     liens[lien_tot]->testmode=0;          // pas mode test
  686.     liens[lien_tot]->link_import=0;       // pas mode import
  687.     liens[lien_tot]->depth=opt.depth+1;   // lien de prioritΘ maximale
  688.     liens[lien_tot]->pass2=0;             // 1Φre passe
  689.     liens[lien_tot]->retry=opt.retry;     // lien de prioritΘ maximale
  690.     liens[lien_tot]->premier=lien_tot;    // premier lien, objet-pΦre=objet              
  691.     liens[lien_tot]->precedent=lien_tot;  // lien prΘcΘdent
  692.     lien_tot++;  
  693.  
  694.     // Initialiser cache
  695.     cache_init(&cache,&opt);
  696.   }
  697.   
  698. #if BDEBUG==3
  699.   {
  700.     int i;
  701.     for(i=0;i<lien_tot;i++) {
  702.       printf("%d>%s%s as %s\n",i,liens[i]->adr,liens[i]->fil,liens[i]->sav);
  703.     }
  704.     for(i=0;i<filptr;i++) {
  705.       printf("%d>filters=%s\n",i,filters[i]);
  706.     }
  707.   }
  708. #endif
  709.    
  710.   // backing
  711.   //soc_max=opt.maxsoc;
  712.   if (opt.maxsoc>0) {
  713. #if BDEBUG==2
  714.     _CLRSCR;
  715. #endif
  716.     // Nombre de fichiers HTML pouvant Ωtre prΘsents en mΘmoire de maniΦre simultannΘe
  717.     // On prΘvoit large: les fichiers HTML ne prennent que peu de place en mΘmoire, et les
  718.     // fichiers non html sont sauvΘs en direct sur disque.
  719.     // --> 1024 entrΘes + 32 entrΘes par socket en supplΘment
  720.     back_max=opt.maxsoc*32+1024;
  721.     //back_max=opt.maxsoc*8+32;
  722.     back=(lien_back*) calloct((back_max+1),sizeof(lien_back));
  723.     if (back==NULL) {
  724.       if (opt.errlog)
  725.         fprintf(opt.errlog,"Not enough memory, can not allocate %d bytes"LF,(opt.maxsoc+1)*sizeof(lien_back));
  726.       return 0;
  727.     } else {    // copier buffer-location & effacer
  728.       int i;
  729.       for(i=0;i<back_max;i++){
  730.         back[i].r.location=back[i].location_buffer;
  731.         back[i].status=-1;
  732.         back[i].r.soc=INVALID_SOCKET;
  733.       }
  734.     }
  735.   }
  736.  
  737.  
  738.   // flush
  739.   test_flush;
  740.  
  741.   // statistiques
  742.   if (opt.makestat) {
  743.     makestat_fp=fopen(fconcat(opt.path_log,"hts-stats.txt"),"wb");
  744.     if (makestat_fp != NULL) {
  745.       fprintf(makestat_fp,"HTTrack statistics report, every minutes"LF LF);
  746.     }
  747.   }
  748.  
  749.   // tracking -- dΘbuggage
  750.   if (opt.maketrack) {
  751.     maketrack_fp=fopen(fconcat(opt.path_log,"hts-track.txt"),"wb");
  752.     if (maketrack_fp != NULL) {
  753.       fprintf(maketrack_fp,"HTTrack tracking report, every minutes"LF LF);
  754.     }
  755.   }
  756.  
  757.   // on n'a pas de liens!! (exemple: httrack www.* impossible sans dΘpart..)
  758.   if (lien_tot<=0) {
  759.     if (opt.errlog) {
  760.       fprintf(opt.errlog,"Error! You MUST specify at least one complete URL, and not only wildcards!"LF);
  761.     }
  762.   }
  763.  
  764.  
  765.   // attendre une certaine heure..
  766.   if (opt.waittime>0) {
  767.     int rollover=0;
  768.     int ok=0;
  769.     {
  770.       double tl=0;
  771.       time_t tt;
  772.       struct tm* A;
  773.       tt=time(NULL);
  774.       A=localtime(&tt);
  775.       tl+=A->tm_sec;
  776.       tl+=A->tm_min*60;
  777.       tl+=A->tm_hour*60*60;
  778.       if (tl>opt.waittime)  // attendre minuit
  779.         rollover=1;
  780.     }
  781.  
  782.     // attendre..
  783.     do {
  784.       double tl=0;
  785.       time_t tt;
  786.       struct tm* A;
  787.       tt=time(NULL);
  788.       A=localtime(&tt);
  789.       tl+=A->tm_sec;
  790.       tl+=A->tm_min*60;
  791.       tl+=A->tm_hour*60*60;
  792.  
  793.       if (rollover) {
  794.         if (tl<=opt.waittime)
  795.           rollover=0;  // attendre heure
  796.       } else {
  797.         if (tl>opt.waittime)
  798.           ok=1;  // ok!
  799.       }
  800.       
  801. #if HTS_ANALYSTE
  802.       {  
  803.         int r;
  804.         if (rollover)
  805.           r=hts_htmlcheck_loop(back,back_max,0,0,lien_tot,0,0,(int) (opt.waittime-tl+24*3600),-1,-1,-1,-1,-1,-1);
  806.         else
  807.           r=hts_htmlcheck_loop(back,back_max,0,0,lien_tot,0,0,(int) (opt.waittime-tl),-1,-1,-1,-1,-1,-1);
  808.         if (!r) {
  809.           exit_xh=1;  // exit requested
  810.           ok=1;          
  811.         } else
  812.           Sleep(100);
  813.       }
  814. #endif
  815.     } while(!ok);    
  816.     
  817.     // note: recopie de plus haut
  818.     // noter heure actuelle de dΘpart en secondes
  819.     HTS_STAT.stat_timestart=time_local();
  820.     if (opt.aff_progress)
  821.       lastime=HTS_STAT.stat_timestart;
  822.     if (opt.shell) {
  823.       last_info_shell=HTS_STAT.stat_timestart;
  824.     }
  825.     if ((opt.makestat) || (opt.maketrack)){
  826.       makestat_time=HTS_STAT.stat_timestart;
  827.     }
  828.  
  829.  
  830.   }  
  831. #if HTS_ANALYSTE
  832.   /*
  833.   if (!hts_htmlcheck_loop(back,back_max,0,0,lien_tot,0,0,0,-1,-1,-1,-1,-1)) {
  834.     XH_extuninit;
  835.     return 1;
  836.   }
  837.   Sleep(100);
  838.   */
  839.   if (!hts_htmlcheck_start()) {
  840.     XH_extuninit;
  841.     return 1;
  842.   }
  843. #endif
  844.   
  845.  
  846.   // ------------------------------------------------------------
  847.  
  848.   // ------------------------------------------------------------
  849.   // Boucle gΘnΘrale de parcours des liens
  850.   // ------------------------------------------------------------
  851.   do {
  852.     int error=0;          // si error alors sauter
  853.     int store_errpage=0;  // c'est une erreur mais on enregistre le html
  854.     char loc[HTS_URLMAXSIZE*2];    // adresse de relocation
  855.  
  856.     // Ici on charge le fichier (html, gif..) en mΘmoire
  857.     // Les HTMLs sont traitΘs (si leur prioritΘ est suffisante)
  858.  
  859.     // effacer r
  860.     bzero((char *)&r, sizeof(htsblk)); r.soc=INVALID_SOCKET;
  861.     r.location=loc;    // en cas d'erreur 3xx (moved)
  862.     // recopier proxy
  863.     bcopy((char*) &opt.proxy,(char*) &(r.req.proxy), sizeof(opt.proxy));
  864.     // et user-agent
  865.     strcpy(r.req.user_agent,opt.user_agent);
  866.     r.req.user_agent_send=opt.user_agent_send;
  867.  
  868.     if (!error) {
  869.       
  870.       // Skip empty/invalid/done in background
  871.       if (liens[ptr]) {
  872.         while (  (liens[ptr]) && (
  873.                     ( ((urladr != NULL)?(urladr):(" "))[0]=='!') ||
  874.                     ( ((urlfil != NULL)?(urlfil):(" "))[0]=='\0') ||
  875.                     ( (liens[ptr]->pass2 == -1) )
  876.                  )
  877.                ) {  // sauter si lien annulΘ (ou fil vide)
  878.           if ((opt.debug>1) && (opt.log!=NULL)) {
  879.             fspc(opt.log,"debug"); fprintf(opt.log,"link #%d seems ready, skipping: %s%s.."LF,ptr,((urladr != NULL)?(urladr):(" ")),((urlfil != NULL)?(urlfil):(" ")));
  880.             test_flush;
  881.           }
  882.           ptr++;
  883.         }
  884.       }
  885.       if (liens[ptr]) {    // on a qq chose α rΘcupΘrer?
  886.  
  887.         if ( (opt.debug>1) && (opt.log!=NULL) ) {
  888.           fspc(opt.log,"debug"); fprintf(opt.log,"Wait get: %s%s"LF,urladr,urlfil);
  889.           test_flush;
  890. #if DEBUG_ROBOTS
  891.           if (strcmp(urlfil,"/robots.txt") == 0) {
  892.             printf("robots.txt detected\n");
  893.           }
  894. #endif
  895.         }    
  896.         // ------------------------------------------------------------
  897.         // DEBUT --RECUPERATION LIEN---
  898.         if (ptr==0) {              // premier lien α parcourir: lien primaire construit avant
  899.           r.adr=primary; primary=NULL;
  900.           r.statuscode=200;
  901.           r.size=strlen(r.adr);
  902.           r.soc=INVALID_SOCKET;
  903.           strcpy(r.contenttype,"text/html");
  904.         /*} else if (opt.maxsoc<=0) {   // fichiers 1 α 1 en attente (pas de backing)
  905.           // charger le fichier en mΘmoire tout bΩtement
  906.           r=xhttpget(urladr,urlfil);
  907.           //
  908.         */
  909.         } else {    // backing, multiples sockets
  910.           //
  911.           int b;
  912.           int n;
  913.           
  914. #if BDEBUG==1
  915.           printf("\nBack test..\n");
  916. #endif
  917.  
  918.           // pause/lock files
  919.           {
  920.             int do_pause=0;
  921.  
  922.             // user pause lockfile : create hts-paused.lock --> HTTrack will be paused
  923.             if (fexist(fconcat(opt.path_log,"hts-stop.lock"))) {
  924.               // remove lockfile
  925.               remove(fconcat(opt.path_log,"hts-stop.lock"));
  926.               if (!fexist(fconcat(opt.path_log,"hts-stop.lock"))) {
  927.                 do_pause=1;
  928.               }
  929.             }
  930.             
  931.             // after receving N bytes, pause
  932.             if (opt.fragment>0) {
  933.               if ((HTS_STAT.stat_bytes-stat_fragment) > opt.fragment) {
  934.                 do_pause=1;
  935.               }
  936.             }
  937.             
  938.             // pause?
  939.             if (do_pause) {
  940.               while (back_nsoc(back,back_max)>0) {                  // attendre fin des transferts
  941.                 back_wait(back,back_max,&opt,&cache,HTS_STAT.stat_timestart);
  942.                 Sleep(100);
  943.               }
  944.               // On dΘsalloue le buffer d'enregistrement des chemins crΘΘe, au cas o∙ pendant la pause
  945.               // l'utilisateur ferait un rm -r aprΦs avoir effectuΘ un tar
  946.               if (structcheck_buff) {
  947.                 freet(structcheck_buff);
  948.                 structcheck_buff=NULL;
  949.               }
  950.               {
  951.                 FILE* fp = fopen(fconcat(opt.path_log,"hts-paused.lock"),"wb");
  952.                 if (fp) {
  953.                   fspc(fp,"info");  // dater
  954.                   fprintf(fp,"Pause"LF"HTTrack is paused after retreiving "LLintP" bytes"LF"Delete this file to continue the mirror..."LF""LF"",HTS_STAT.stat_bytes);
  955.                   fclose(fp);
  956.                 }
  957.               }
  958.               stat_fragment=HTS_STAT.stat_bytes;
  959.               while (fexist(fconcat(opt.path_log,"hts-paused.lock"))) {
  960.                 //back_wait(back,back_max,&opt,&cache,HTS_STAT.stat_timestart);   inutile!! (plus de sockets actives)
  961.                 Sleep(1000);
  962.               }
  963.             }
  964.             //
  965.           }
  966.           // end of pause/lock files
  967.           
  968. #if HTS_ANALYSTE==2
  969.           // changement dans les prΘfΘrences
  970.           if (_hts_setopt) {
  971.             copy_htsopt(_hts_setopt,&opt);    // copier au besoin
  972.             _hts_setopt=NULL;                 // effacer callback
  973.           }
  974.           if (_hts_addurl) {
  975.             char add_adr[HTS_URLMAXSIZE*2];
  976.             char add_fil[HTS_URLMAXSIZE*2];
  977.             while(*_hts_addurl) {
  978.               char add_url[HTS_URLMAXSIZE*2];
  979.               add_adr[0]=add_fil[0]=add_url[0]='\0';
  980.               if (strstr(*_hts_addurl,"://")==NULL)
  981.                 strcpy(add_url,"http://");          // ajouter http://
  982.               strcat(add_url,*_hts_addurl);
  983.               if (ident_url(add_url,add_adr,add_fil)>=0) {
  984.                 // ----Ajout----
  985.                 // noter NOUVEAU lien
  986.                 char add_sav[HTS_URLMAXSIZE*2];
  987.                 // calculer lien et Θventuellement modifier addresse/fichier
  988.                 if (url_savename(add_adr,add_fil,add_sav,NULL,NULL,NULL,NULL,&opt,liens,lien_tot,back,back_max,&cache,&hash,ptr,numero_passe)!=-1) { 
  989.                   if (hash_read(&hash,add_sav,"",0)<0) {      // n'existe pas dΘja
  990.                     // enregistrer lien (MACRO)
  991.                     liens_record(add_adr,add_fil,add_sav,"","");
  992.                     if (liens[lien_tot]!=NULL) {    // OK, pas d'erreur
  993.                       liens[lien_tot]->testmode=0;          // mode test?
  994.                       liens[lien_tot]->link_import=0;       // mode normal
  995.                       liens[lien_tot]->depth=opt.depth;
  996.                       liens[lien_tot]->pass2=max(0,numero_passe);
  997.                       liens[lien_tot]->retry=opt.retry;
  998.                       liens[lien_tot]->premier=lien_tot;
  999.                       liens[lien_tot]->precedent=lien_tot;
  1000.                       lien_tot++;
  1001.                       //
  1002.                       if ((opt.debug>0) && (opt.log!=NULL)) {
  1003.                         fspc(opt.log,"info"); fprintf(opt.log,"Link added by user: %s%s"LF,add_adr,add_fil); test_flush;
  1004.                       }
  1005.                       //
  1006.                     } else {  // oups erreur, plus de mΘmoire!!
  1007.                       printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  1008.                       if (opt.errlog) {
  1009.                         fprintf(opt.errlog,"Not enough memory, can not re-allocate %d bytes"LF,(add_tab_alloc+1)*sizeof(lien_url));
  1010.                         test_flush;
  1011.                       }
  1012.                       //if (opt.getmode & 1) { if (fp) { fclose(fp); fp=NULL; } }
  1013.                       XH_uninit;    // dΘsallocation mΘmoire & buffers
  1014.                       return 0;
  1015.                     }
  1016.                   } else {
  1017.                     if ( (opt.debug>0) && (opt.errlog!=NULL) ) {
  1018.                       fspc(opt.errlog,"warning"); fprintf(opt.errlog,"Existing link %s not added after user request"LF,add_adr,add_fil);
  1019.                       test_flush;
  1020.                     }
  1021.                   }
  1022.                   
  1023.                 }
  1024.               } else {
  1025.                 if (opt.errlog) {
  1026.                   fspc(opt.errlog,"error");
  1027.                   fprintf(opt.errlog,"Error during URL decoding for %s%s"LF,add_url);
  1028.                   test_flush;
  1029.                 }
  1030.               }
  1031.               // ----Fin Ajout----
  1032.               _hts_addurl++;                  // suivante
  1033.             }
  1034.             _hts_addurl=NULL;           // libΘrer _hts_addurl
  1035.           }
  1036.           // si une pause a ΘtΘ demandΘe
  1037.           if (_hts_setpause) {
  1038.             // index du lien actuel
  1039.             int b=back_index(back,back_max,urladr,urlfil,savename);
  1040.             if (b<0) b=0;    // forcer pour les stats
  1041.             while(_hts_setpause) {    // on fait la pause..
  1042.               LLint nb;
  1043.               int nbk;
  1044.               back_wait(back,back_max,&opt,&cache,HTS_STAT.stat_timestart);
  1045.               nb=back_transfered(HTS_STAT.stat_bytes,back,back_max);
  1046.               nbk=backlinks_done(liens,lien_tot,ptr);
  1047.               engine_stats();
  1048.               if (!hts_htmlcheck_loop(back,back_max,b,ptr,lien_tot,nb,new_stat_bytes,(int) (time_local()-HTS_STAT.stat_timestart),back_nsoc(back,back_max),HTS_STAT.stat_files,HTS_STAT.stat_updated_files,fspc(NULL,"error"),(int)HTS_STAT.rate,nbk )) {
  1049.                 if (opt.errlog) {
  1050.                   fspc(opt.errlog,"info"); fprintf(opt.errlog,"Exit requested by shell or user"LF);
  1051.                   test_flush;
  1052.                 }
  1053.                 exit_xh=1;  // exit requested
  1054.                 XH_uninit;
  1055.                 return 0;
  1056.               }
  1057.               if (back_nsoc(back,back_max)==0)
  1058.                 Sleep(250);  // tite pause
  1059.             }
  1060.           }
  1061. #endif
  1062.           
  1063.           // si le fichier n'est pas en backing, le mettre..
  1064.           if (!back_exist(back,back_max,urladr,urlfil,savename)) {
  1065. #if BDEBUG==1
  1066.             printf("crash backing: %s%s\n",liens[ptr]->adr,liens[ptr]->fil);
  1067. #endif
  1068.             if (back_add(back,back_max,&opt,&cache,urladr,urlfil,savename,liens[liens[ptr]->precedent]->adr,liens[liens[ptr]->precedent]->fil,liens[ptr]->testmode,&liens[ptr]->pass2)==-1) {
  1069.               printf("PANIC! : Crash adding error, unexpected error found.. [%d]\n",__LINE__);
  1070. #if BDEBUG==1
  1071.               printf("error while crash adding\n");
  1072. #endif
  1073.               if (opt.errlog) {
  1074.                 fspc(opt.errlog,"error"); fprintf(opt.errlog,"Unexpected backing error for %s%s"LF,urladr,urlfil);
  1075.                 test_flush;
  1076.               } 
  1077.               
  1078.             }
  1079.           }
  1080.           
  1081. #if BDEBUG==1
  1082.           printf("test number of socks\n");
  1083. #endif
  1084.           
  1085.           // ajouter autant de socket qu'on peut ajouter
  1086.           n=opt.maxsoc-back_nsoc(back,back_max);
  1087. #if BDEBUG==1
  1088.           printf("%d sockets available for backing\n",n);
  1089. #endif
  1090.  
  1091. #if HTS_ANALYSTE==2
  1092.           if ((n>0) && (!_hts_setpause)) {   // si sockets libre et pas en pause, ajouter
  1093. #else
  1094.           if (n>0) {                         // si sockets libre
  1095. #endif
  1096.             // remplir autant que l'on peut le cache (backing)
  1097.             back_fillmax(back,back_max,&opt,&cache,liens,ptr,numero_passe,lien_tot);
  1098.           }
  1099.           
  1100.           // index du lien actuel
  1101. /*
  1102.           b=back_index(back,back_max,urladr,urlfil,savename);
  1103.           
  1104.           if (b>=0) 
  1105. */
  1106.           {
  1107.             // ------------------------------------------------------------
  1108.             // attendre que le fichier actuel soit prΩt - BOUCLE D'ATTENTE
  1109.             do {
  1110.  
  1111.               // index du lien actuel
  1112.               b=back_index(back,back_max,urladr,urlfil,savename);
  1113. #if BDEBUG==1
  1114.               printf("back index %d, waiting\n",b);
  1115. #endif
  1116.               // Continue to the loop if link still present
  1117.               if (b<0)
  1118.                 continue;
  1119.               
  1120.               // Receive data
  1121.               if (back[b].status>0)
  1122.                 back_wait(back,back_max,&opt,&cache,HTS_STAT.stat_timestart);
  1123.               
  1124.               // Continue to the loop if link still present
  1125.               b=back_index(back,back_max,urladr,urlfil,savename);
  1126.               if (b<0)
  1127.                 continue;
  1128.               
  1129.               // And fill the backing stack
  1130.               if (back[b].status>0)
  1131.                 back_fillmax(back,back_max,&opt,&cache,liens,ptr,numero_passe,lien_tot);
  1132.               
  1133.               // Continue to the loop if link still present
  1134.               b=back_index(back,back_max,urladr,urlfil,savename);
  1135.               if (b<0)
  1136.                 continue;
  1137.  
  1138.               // autres occupations de HTTrack: statistiques, boucle d'attente, etc.
  1139.               if ((opt.makestat) || (opt.maketrack)) {
  1140.                 double l=time_local();
  1141.                 if ((int) (l-makestat_time) >= 60) {   
  1142.                   if (makestat_fp != NULL) {
  1143.                     fspc(makestat_fp,"info");
  1144.                     fprintf(makestat_fp,"Rate= %d (/"LLintP") \11NewLinks= %d (/%d)"LF,(int) ((new_stat_bytes-makestat_total)/(l-makestat_time)), new_stat_bytes,(int) lien_tot-makestat_lnk,(int) lien_tot);
  1145.                     fflush(makestat_fp);
  1146.                     makestat_total=new_stat_bytes;
  1147.                     makestat_lnk=lien_tot;
  1148.                   }
  1149.                   if (maketrack_fp!=NULL) {
  1150.                     int i;
  1151.                     fspc(maketrack_fp,"info"); fprintf(maketrack_fp,LF);
  1152.                     for(i=0;i<back_max;i++) {
  1153.                       back_info(back,i,3,maketrack_fp);
  1154.                     }
  1155.                     fprintf(maketrack_fp,LF);
  1156.                     
  1157.                   }
  1158.                   makestat_time=l;
  1159.                 }
  1160.               }
  1161. #if HTS_ANALYSTE==2
  1162.               {
  1163.                 LLint nb;
  1164.                 int nbk;
  1165.                 int i;
  1166.                 {
  1167.                   char* s=hts_cancel_file("");
  1168.                   if (strnotempty(s)) {    // fichier α canceller
  1169.                     for(i=0;i<back_max;i++) {
  1170.                       if ((back[i].status>0)) {
  1171.                         if (strcmp(back[i].url_sav,s)==0) {  // ok trouvΘ
  1172.                           if (back[i].status != 1000) {
  1173. #if HTS_DEBUG_CLOSESOCK
  1174.                             DEBUG_W("user cancel: deletehttp\n");
  1175. #endif
  1176.                             if (back[i].r.soc!=INVALID_SOCKET) deletehttp(&back[i].r);
  1177.                             back[i].r.soc=INVALID_SOCKET;
  1178.                             back[i].r.statuscode=-1;
  1179.                             strcpy(back[i].r.msg,"Cancelled by User");
  1180.                             back[i].status=0;  // terminΘ
  1181.                           } else    // cancel ftp.. flag α 1
  1182.                             back[i].stop_ftp = 1;
  1183.                         }
  1184.                       }
  1185.                     }
  1186.                     s[0]='\0';
  1187.                   }
  1188.                 }
  1189.                 
  1190.                 engine_stats();
  1191.                 nb=back_transfered(HTS_STAT.stat_bytes,back,back_max);
  1192.                 nbk=backlinks_done(liens,lien_tot,ptr);
  1193.                 if (!hts_htmlcheck_loop(back,back_max,b,ptr,lien_tot,nb,new_stat_bytes,(int) (time_local()-HTS_STAT.stat_timestart),back_nsoc(back,back_max),HTS_STAT.stat_files,HTS_STAT.stat_updated_files,fspc(NULL,"error"),(int)HTS_STAT.rate,nbk )) {
  1194.                   if (opt.errlog) {
  1195.                     fspc(opt.errlog,"info"); fprintf(opt.errlog,"Exit requested by shell or user"LF);
  1196.                     test_flush;
  1197.                   } 
  1198.                   exit_xh=1;  // exit requested
  1199.                   XH_uninit;
  1200.                   return 0;
  1201.                 }
  1202.               }
  1203.               
  1204. #endif
  1205. #if HTS_POLL      
  1206.               if ((opt.shell) || (opt.keyboard)) {
  1207.                 int rcvd=0;
  1208.                 double tl;
  1209.                 info_shell=1;
  1210.                 // Traitement Θventuel des requΦtes stdin etc.
  1211.                 while (check_stdin()) {  // donnΘes disponibles
  1212.                   char com[256];
  1213.                   com[0]='\0';
  1214.                   
  1215.                   if (!rcvd) rcvd=1;
  1216.                   linput(stdin,com,256);
  1217.  
  1218.                   if (strnotempty(com)) {
  1219.                     if (strlen(com)<=2) {
  1220.                       switch(*com) {
  1221.                       case '?': {    // Status?
  1222.                         if (back[b].status>0) printf("WAIT\n"); 
  1223.                         else printf("READY\n");
  1224.                                 }
  1225.                         break;
  1226.                       case 'f': {    // Fichier en attente?
  1227.                         if (back[b].status>0) printf("WAIT %s\n",back[b].url_fil); 
  1228.                         else printf("READY %s\n",back[b].url_fil);
  1229.                                 }
  1230.                         break;
  1231.                       case 'A': case 'F': {    // filters
  1232.                         int i;
  1233.                         for(i=0;i<filptr;i++) {
  1234.                           printf("%s ",filters[i]);
  1235.                         }
  1236.                         printf("\n");
  1237.                                 }
  1238.                         break;
  1239.                       case '#': {    // Afficher statistique sur le nombre de liens, etc
  1240.                         switch(*(com+1)) {
  1241.                         case 'l': printf("%d\n",lien_tot); break;  // nombre de liens enregistrΘs
  1242.                         case 's': printf("%d\n",back_nsoc(back,back_max)); break;  // nombre de sockets
  1243.                         case 'r': printf("%d\n",(int) (new_stat_bytes/(time_local()-HTS_STAT.stat_timestart))); break;  // taux de transfert
  1244.                         }
  1245.                                 }
  1246.                         break;
  1247.                       case 'K': if (*(com+1)=='!') {  // Kill
  1248.                         XH_uninit;
  1249.                         return -1;
  1250.                                 }
  1251.                         break;
  1252.                       case 'X': if (*(com+1)=='!') {  // exit
  1253.                         exit_xh=1;
  1254.                                 }
  1255.                         break;
  1256.                       case 'I': if (*(com+1)=='+') info_shell=1; else info_shell=0;
  1257.                         break;
  1258.                       }
  1259.                       io_flush;
  1260.                     } else if (*com=='@') {
  1261.                       printf("%s\n",com+1);
  1262.                       io_flush;
  1263.                     }
  1264.                   } 
  1265.                   
  1266.                 }  // while
  1267.                 tl=time_local();
  1268.                 
  1269.                 // gΘnΘrer un message d'infos sur l'Θtat actuel
  1270.                 if (opt.shell) {    // si shell
  1271.                   if ((tl-last_info_shell)>0) {    // toute les 1 sec
  1272.                     FILE* fp=stdout;
  1273.                     int a=0;
  1274.                     last_info_shell=tl;
  1275.                     if (fexist(fconcat(opt.path_log,"hts-autopsy"))) {  // dΘbuggage: teste si le robot est vivant
  1276.                       // (oui je sais un robot vivant.. mais bon.. il a le droit de vivre lui aussi)
  1277.                       // (libΘrons les robots esclaves de l'internet!)
  1278.                       remove(fconcat(opt.path_log,"hts-autopsy"));
  1279.                       fp=fopen(fconcat(opt.path_log,"hts-isalive"),"wb");
  1280.                       a=1;
  1281.                     }
  1282.                     if ((info_shell) || a) {
  1283.                       int i,j;
  1284.                       
  1285.                       fprintf(fp,"TIME %d"LF,(int) (tl-HTS_STAT.stat_timestart));
  1286.                       fprintf(fp,"TOTAL %d"LF,(int) HTS_STAT.stat_bytes);
  1287.                       fprintf(fp,"RATE %d"LF,(int) (new_stat_bytes/(tl-HTS_STAT.stat_timestart)));
  1288.                       fprintf(fp,"SOCKET %d"LF,back_nsoc(back,back_max));
  1289.                       fprintf(fp,"LINK %d"LF,lien_tot);
  1290.                       {
  1291.                         LLint mem=0;
  1292.                         for(i=0;i<back_max;i++)
  1293.                           if (back[i].r.adr!=NULL)
  1294.                             mem+=back[i].r.size;
  1295.                           fprintf(fp,"INMEM "LLintP""LF,mem);
  1296.                       }
  1297.                       for(j=0;j<2;j++) {  // passes pour ready et wait
  1298.                         for(i=0;i<back_max;i++) {
  1299.                           back_info(back,i,j+1,stdout);    // maketrack_fp a la place de stdout ?? // **
  1300.                         }
  1301.                       }
  1302.                       fprintf(fp,LF);
  1303.                       if (a)
  1304.                         fclose(fp);
  1305.                       io_flush;
  1306.                     }
  1307.                   }
  1308.                 }  // si shell
  1309.                 
  1310.               }  // si shell ou keyboard (option)
  1311.               //
  1312. #endif
  1313.             } while((b>=0) && (back[max(b,0)].status>0));
  1314.  
  1315.  
  1316.             // If link not found on the stack, it's because it has already been downloaded
  1317.             // in background
  1318.             // Then, skip it and go to the next one
  1319.             if (b<0) {
  1320.               if ((opt.debug>1) && (opt.log!=NULL)) {
  1321.                 fspc(opt.log,"debug"); fprintf(opt.log,"link #%d is ready, no more on the stack, skipping: %s%s.."LF,ptr,urladr,urlfil);
  1322.                 test_flush;
  1323.               }
  1324.  
  1325.               // prochain lien
  1326.               ptr++;
  1327.  
  1328.               // Jump to 'continue'
  1329.               // This is one of the very very rare cases where goto
  1330.               // is acceptable
  1331.               // A supplemental flag and if() { } would be really messy
  1332.               goto jump_if_done;
  1333.             }
  1334.             
  1335.  
  1336. #if HTS_ANALYSTE
  1337. #else
  1338.             if (!opt.quiet) {  // petite animation
  1339.               if (!opt.verbosedisplay) {
  1340.                 static int roll=0;
  1341.                 roll=(roll+1)%4;
  1342.                 printf("%c\x0d",("/-\\|")[roll]);
  1343.                 fflush(stdout);
  1344.               } else {
  1345.                 if (back[b].r.statuscode==200)
  1346.                   printf("%d/%d: %s%s ("LLintP" bytes) - OK\33[K\r",ptr,lien_tot,back[b].url_adr,back[b].url_fil,back[b].r.size);
  1347.                 else
  1348.                   printf("%d/%d: %s%s ("LLintP" bytes) - %d\33[K\r",ptr,lien_tot,back[b].url_adr,back[b].url_fil,back[b].r.size,back[b].r.statuscode);
  1349.                 fflush(stdout);
  1350.               }
  1351.             }
  1352. #endif
  1353.             // ------------------------------------------------------------
  1354.             // VΘrificateur d'intΘgritΘ
  1355. #if DEBUG_CHECKINT
  1356.             _CHECKINT(&back[b],"Retour de back_wait, aprΦs le while")
  1357.             {
  1358.               int i;
  1359.               for(i=0;i<back_max;i++) {
  1360.                 char si[256];
  1361.                 sprintf(si,"Test global aprΦs back_wait, index %d",i);
  1362.                 _CHECKINT(&back[i],si)
  1363.               }
  1364.             }
  1365. #endif
  1366.             
  1367.             // copier structure rΘponse htsblk
  1368.             bcopy((char*) &(back[b].r), (char*) &r, sizeof(htsblk));
  1369.             r.location=loc;    // ne PAS copier location!! adresse, pas de buffer
  1370.             if (back[b].r.location) 
  1371.               strcpy(r.location,back[b].r.location);
  1372.             back[b].r.adr=NULL;    // ne pas faire de desalloc ensuite
  1373.  
  1374.             // libΘrer emplacement backing
  1375.             back_delete(back,b);
  1376.             
  1377.             // progression
  1378.             if (opt.aff_progress) {
  1379.               double tl=time_local();
  1380.               if ((tl-lastime)>0) {
  1381.                 char s[32];
  1382.                 int i=0;
  1383.                 lastime=tl;
  1384.                 _CLRSCR; _GOTOXY("1","1");
  1385.                 printf("Rate=%d B/sec\n",(int) (new_stat_bytes/(tl-HTS_STAT.stat_timestart)));
  1386.                 while(i<minimum(back_max,99)) {  // **
  1387.                   if (back[i].status>=0) {  // loading..
  1388.                     s[0]='\0';
  1389.                     if (strlen(back[i].url_fil)>16)
  1390.                       strcat(s,back[i].url_fil+strlen(back[i].url_fil)-16);       
  1391.                     else
  1392.                       strncat(s,back[i].url_fil,16);
  1393.                     printf("%s : ",s);
  1394.                     
  1395.                     printf("[");
  1396.                     if (back[i].r.totalsize>0) {
  1397.                       int p;
  1398.                       int j;
  1399.                       p=(int)((back[i].r.size*10)/back[i].r.totalsize);
  1400.                       p=minimum(10,p);
  1401.                       for(j=0;j<p;j++) printf("*");
  1402.                       for(j=0;j<(10-p);j++) printf("-");
  1403.                     } else { 
  1404.                       printf(LLintP,back[i].r.size);                      
  1405.                     }
  1406.                     printf("]");
  1407.                     
  1408.                     //} else if (back[i].status==0) {
  1409.                     //  strcpy(s,"ENDED");
  1410.                   } 
  1411.                   printf("\n");
  1412.                   i++;
  1413.                 }
  1414.                 io_flush;
  1415.               }
  1416.             }
  1417.             
  1418.             // dΘbug graphique
  1419. #if BDEBUG==2
  1420.             {
  1421.               char s[12];
  1422.               int i=0;
  1423.               _GOTOXY(1,1);
  1424.               printf("Rate=%d B/sec\n",(int) (new_stat_bytes/(time_local()-HTS_STAT.stat_timestart)));
  1425.               while(i<minimum(back_max,160)) {
  1426.                 if (back[i].status>0) {
  1427.                   sprintf(s,"%d",back[i].r.size);
  1428.                 } else if (back[i].status==0) {
  1429.                   strcpy(s,"ENDED");
  1430.                 } else 
  1431.                   strcpy(s,"   -   ");
  1432.                 while(strlen(s)<8) strcat(s," ");
  1433.                 printf("%s",s); io_flush;
  1434.                 i++;
  1435.               }
  1436.             }
  1437. #endif
  1438.             
  1439.             
  1440. #if BDEBUG==1
  1441.             printf("statuscode=%d with %s / msg=%s\n",r.statuscode,r.contenttype,r.msg);
  1442. #endif
  1443.             
  1444.           }
  1445.           /*else {
  1446. #if BDEBUG==1
  1447.             printf("back index error\n");
  1448. #endif
  1449.           }
  1450.           */
  1451.           
  1452.         }
  1453.         // FIN --RECUPERATION LIEN--- 
  1454.         // ------------------------------------------------------------
  1455.  
  1456.  
  1457.  
  1458.       } else {    // lien vide..
  1459.         if (opt.errlog) {
  1460.           fspc(opt.errlog,"warning"); fprintf(opt.errlog,"Warning, link #%d empty"LF,ptr); test_flush;
  1461.           error=1;
  1462.         }         
  1463.       }  // test si url existe (non vide!)
  1464.       
  1465.  
  1466.  
  1467.       // ---tester taille a posteriori---
  1468.       // tester r.adr
  1469.       if (!error) {
  1470.         // erreur, pas de fichier chargΘ:
  1471.         if ((!r.adr) && (r.is_write==0) 
  1472.           && (r.statuscode!=301) 
  1473.           && (r.statuscode!=302) 
  1474.           && (r.statuscode!=303) 
  1475.           && (r.statuscode!=307) 
  1476.           && (r.statuscode!=412)
  1477.           && (r.statuscode!=416)
  1478.          ) { 
  1479.           error=1;
  1480.           
  1481.           // peut Ωtre que le fichier Θtait trop gros?
  1482.           if ((istoobig(r.totalsize,opt.maxfile_html,opt.maxfile_nonhtml,r.contenttype))
  1483.            || (istoobig(r.totalsize,opt.maxfile_html,opt.maxfile_nonhtml,r.contenttype))) {
  1484.             error=0;
  1485.             if (opt.errlog) {
  1486.               fspc(opt.errlog,"warning"); fprintf(opt.errlog,"Big file cancelled according to user's preferences: %s%s"LF,urladr,urlfil);
  1487.               test_flush;
  1488.             }
  1489.           }
  1490.           error=1;    // ne pas traiter la suite -- euhh si finalement..
  1491.         }
  1492.       }
  1493.       // ---fin tester taille a posteriori---    
  1494.  
  1495.  
  1496.       // -------------------- 
  1497.       // BOGUS MIME TYPE HACK
  1498.       // Check if we have a bogus MIME type
  1499.       // example: 
  1500.       // Content-type="text/html"
  1501.       // and 
  1502.       // Content-disposition="foo.jpg"
  1503.       // --------------------
  1504.       if (!error) {
  1505.         if (r.adr) {    // Written file
  1506.           if ( (is_hypertext_mime(r.contenttype))   /* Is HTML or Js, .. */
  1507.             || (may_be_hypertext_mime(r.contenttype) && (r.adr) )  /* Is real media, .. */
  1508.             ) {
  1509.             if (strnotempty(r.cdispo)) {      // Content-disposition set!
  1510.               if (ishtml(savename) == 0) {    // Non HTML!!
  1511.                 // patch it!
  1512.                 strcpy(r.contenttype,"application/octet-stream");
  1513.               }
  1514.             }
  1515.           }
  1516.         }
  1517.       }
  1518.       
  1519.  
  1520.       // -------------------- 
  1521.       // REAL MEDIA HACK
  1522.       // Check if we have to load locally the file
  1523.       // --------------------
  1524.       if (!error) {
  1525.         if (r.adr==NULL) {    // Written file
  1526.           if (may_be_hypertext_mime(r.contenttype)) {   // to parse!
  1527.             LLint sz;
  1528.             sz=fsize(savename);
  1529.             if (sz>0) {   // ok, exists!
  1530.               if (sz < 512) {   // ok, small file --> to parse!
  1531.                 FILE* fp=fopen(savename,"rb");
  1532.                 if (fp) {
  1533.                   r.adr=malloc((int)sz + 2);
  1534.                   if (r.adr) {
  1535.                     fread(r.adr,(int)sz,1,fp);
  1536.                     r.size=sz;
  1537.                     // remove (temporary) file!
  1538.                     remove(savename);
  1539.                   }
  1540.                   fclose(fp);
  1541.                 }
  1542.               }
  1543.             }
  1544.           }
  1545.         }
  1546.       }
  1547.       // EN OF REAL MEDIA HACK
  1548.       
  1549.  
  1550.       // ---stockage en cache---
  1551.       // stocker dans le cache?
  1552.       if (!error) {
  1553.         if (ptr>0) {
  1554.           if (liens[ptr]) {
  1555.             cache_mayadd(&opt,&cache,&r,urladr,urlfil,savename);
  1556. #if 0        
  1557.             if (opt.cache) {
  1558.               if (cache.dat!=NULL) {
  1559.                 // c'est le seul endroit ou l'on ajoute des elements dans le cache (fichier entier ou header)
  1560.                 // on stocke tout fichier "ok", mais Θgalement les rΘponses 404,301,302...
  1561.                 if ((r.statuscode==200)         /* stocker rΘponse standard, plus */
  1562.                   || (r.statuscode==204)     /* no content */
  1563.                   || (r.statuscode==301)     /* moved perm */
  1564.                   || (r.statuscode==302)     /* moved temp */
  1565.                   || (r.statuscode==303)     /* moved temp */
  1566.                   || (r.statuscode==307)     /* moved temp */
  1567.                   || (r.statuscode==401)     /* authorization */
  1568.                   || (r.statuscode==403)     /* unauthorized */
  1569.                   || (r.statuscode==404)     /* not found */
  1570.                   || (r.statuscode==410)     /* gone */
  1571.                   )
  1572.                 {        /* ne pas stocker si la page gΘnΘrΘe est une erreur */
  1573.                   if (!r.is_file) {
  1574.                     // stocker fichiers (et robots.txt)
  1575.                     if ( (strnotempty(savename)) || (strcmp(urlfil,"/robots.txt")==0)) {
  1576.                       // ajouter le fichier au cache
  1577.                       cache_add(r,urladr,urlfil,savename,cache.ndx,cache.dat,opt.all_in_cache);
  1578.                     }
  1579.                   }
  1580.                 }
  1581.               }
  1582.             }
  1583. #endif
  1584.           } else
  1585.             error=1;
  1586.         }
  1587.       }
  1588.       // ---fin stockage en cache---
  1589.       
  1590.  
  1591.  
  1592.       // DEBUT rattrapage des 301,302,307..
  1593.       // ------------------------------------------------------------
  1594.       if (!error) {
  1595.       ////////{
  1596.         // on a chargΘ un fichier en plus
  1597.         // if (!error) stat_loaded+=r.size;
  1598.         
  1599.         // ------------------------------------------------------------
  1600.         // Rattrapage des 301,302,307 (moved) et 412,416 - les 304 le sont dans le backing 
  1601.         // ------------------------------------------------------------
  1602.         if ( (r.statuscode==301) 
  1603.           || (r.statuscode==302)
  1604.           || (r.statuscode==303)
  1605.           || (r.statuscode==307)
  1606.           ) {          
  1607.           //if (r.adr!=NULL) {   // adr==null si fichier direct. [catch: davename normalement si cgi]
  1608.             //int i=0;
  1609.             char *rn=NULL;
  1610.             char* p;
  1611.             
  1612.             if ( (opt.debug>0) && (opt.errlog!=NULL) ) {
  1613.             //if (opt.errlog) {
  1614.               fspc(opt.errlog,"warning"); fprintf(opt.errlog,"%s for %s%s"LF,r.msg,urladr,urlfil);
  1615.               test_flush;
  1616.             }
  1617.             
  1618.             
  1619. #if 0
  1620.             //do {
  1621.             //  if (strfield(r.adr+i,"href=")) {    // URL trouvΘe
  1622. #endif
  1623.             {
  1624.               char mov_url[HTS_URLMAXSIZE*2],mov_adr[HTS_URLMAXSIZE*2],mov_fil[HTS_URLMAXSIZE*2];
  1625.               int n=0;
  1626.               int reponse=0;
  1627.               mov_url[0]='\0'; mov_adr[0]='\0'; mov_fil[0]='\0';
  1628.               //
  1629.               //printf("location panic! %s\n",r.location);
  1630.               
  1631.               ////p=r.adr+i;
  1632.               ////p+=5;    // sauter href
  1633.               p=r.location;
  1634.               while(is_space(*p)) p++;  // sauter espaces, " & cie
  1635.               while((!is_space(p[n])) && (p[n] != 0) && (p[n] != '>')) n++;  // compter caractΦres
  1636.               strcpy (mov_url,"");
  1637.               strncat(mov_url,p,n);    // copier URL
  1638.               
  1639.               // url qque -> adresse+fichier
  1640.               if ((reponse=ident_url_relatif(mov_url,urladr,urlfil,mov_adr,mov_fil))>=0) {                        
  1641.                 int get_it=0;         // ne pas prendre le fichier α la mΩme adresse par dΘfaut
  1642.                 int set_prio_to=0;    // pas de priotitΘ fixΘd par wizard
  1643.                 
  1644.                 //if (ident_url(mov_url,mov_adr,mov_fil)!=-1) {    // ok URL reconnue
  1645.                 // c'est (en gros) la mΩme URL..
  1646.                 // si c'est un problΦme de casse dans le host c'est que le serveur est buggΘ
  1647.                 // ("RFC says.." : host name IS case insensitive)
  1648.                 if ((strfield2(mov_adr,urladr)!=0) && (strfield2(mov_fil,urlfil)!=0)) {  // identique α casse prΦs
  1649.                   // on tourne en rond
  1650.                   if (strcmp(mov_fil,urlfil)==0) {
  1651.                     error=1;
  1652.                     get_it=-1;        // ne rien faire
  1653.                     if (opt.errlog) {
  1654.                       fspc(opt.errlog,"warning"); fprintf(opt.errlog,"Can not bear crazy server (%s) for %s%s"LF,r.msg,urladr,urlfil);
  1655.                       test_flush;
  1656.                     }
  1657.                   } else {    // mauvaise casse, effacer entrΘe dans la pile et rejouer une fois
  1658.                     get_it=1;
  1659.                   }
  1660.                 } else {
  1661.                   if (ishtml(mov_url)==0) {   // pas mΩme adresse MAIS c'est un fichier (pas de page moved possible)
  1662.                     // -> on prend α cette adresse, le lien sera enregistrΘ avec lien_record() (hash)
  1663.                     if ((opt.debug>1) && (opt.log!=NULL)) {
  1664.                       fspc(opt.log,"debug"); fprintf(opt.log,"wizard link test for moved file at %s%s.."LF,mov_adr,mov_fil);
  1665.                       test_flush;
  1666.                     }
  1667.                     if (hts_acceptlink(&opt,ptr,lien_tot,liens,
  1668.                       mov_adr,mov_fil,
  1669.                       filters,&filptr,filter_max,
  1670.                       &robots,
  1671.                       &set_prio_to,
  1672.                       NULL) != 1) {                /* nouvelle adresse non refusΘe ? */
  1673.                       get_it=1;
  1674.                       if ((opt.debug>1) && (opt.log!=NULL)) {
  1675.                         fspc(opt.log,"debug"); fprintf(opt.log,"moved link accepted: %s%s"LF,mov_adr,mov_fil);
  1676.                         test_flush;
  1677.                       }
  1678.                     }
  1679.                   } /* sinon traitΘ normalement */
  1680.                 }
  1681.                 
  1682.                 //if ((strfield2(mov_adr,urladr)!=0) && (strfield2(mov_fil,urlfil)!=0)) {  // identique α casse prΦs
  1683.                 if (get_it==1) {
  1684.                   // court-circuiter le reste du traitement
  1685.                   // et reculer pour mieux sauter
  1686.                   if (opt.errlog) {
  1687.                     fspc(opt.errlog,"warning"); fprintf(opt.errlog,"Warning wrong case ignored for %s%s (real one is %s%s)"LF,urladr,urlfil,mov_adr,mov_fil);
  1688.                     test_flush;
  1689.                   }          
  1690.                   // canceller lien actuel
  1691.                   error=1;
  1692.                   strcpy(liens[ptr]->adr,"!");  // caractΦre bidon (invalide hash)
  1693. #if HTS_HASH
  1694. #else
  1695.                   liens[ptr]->sav_len=-1;       // taille invalide
  1696. #endif
  1697.                   // noter NOUVEAU lien
  1698.                   {
  1699.                     char mov_sav[HTS_URLMAXSIZE*2];
  1700.                     // calculer lien et Θventuellement modifier addresse/fichier
  1701.                     if (url_savename(mov_adr,mov_fil,mov_sav,NULL,NULL,liens[liens[ptr]->precedent]->adr,liens[liens[ptr]->precedent]->fil,&opt,liens,lien_tot,back,back_max,&cache,&hash,ptr,numero_passe)!=-1) { 
  1702.                       if (hash_read(&hash,mov_sav,"",0)<0) {      // n'existe pas dΘja
  1703.                         // enregistrer lien (MACRO) avec SAV IDENTIQUE
  1704.                         liens_record(mov_adr,mov_fil,liens[ptr]->sav,"","");
  1705.                         //liens_record(mov_adr,mov_fil,mov_sav,"","");
  1706.                         if (liens[lien_tot]!=NULL) {    // OK, pas d'erreur
  1707.                           // mode test?
  1708.                           liens[lien_tot]->testmode=liens[ptr]->testmode;
  1709.                           liens[lien_tot]->link_import=0;       // mode normal
  1710.                           if (!set_prio_to)
  1711.                             liens[lien_tot]->depth=liens[ptr]->depth;
  1712.                           else
  1713.                             liens[lien_tot]->depth=max(0,min(set_prio_to-1,liens[ptr]->depth));       // PRIORITE NULLE (catch page)
  1714.                           liens[lien_tot]->pass2=max(liens[ptr]->pass2,numero_passe);
  1715.                           liens[lien_tot]->retry=liens[ptr]->retry;
  1716.                           liens[lien_tot]->premier=liens[ptr]->premier;
  1717.                           liens[lien_tot]->precedent=liens[ptr]->precedent;
  1718.                           lien_tot++;
  1719.                         } else {  // oups erreur, plus de mΘmoire!!
  1720.                           printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  1721.                           if (opt.errlog) {
  1722.                             fprintf(opt.errlog,"Not enough memory, can not re-allocate %d bytes"LF,(add_tab_alloc+1)*sizeof(lien_url));
  1723.                             test_flush;
  1724.                           }
  1725.                           //if (opt.getmode & 1) { if (fp) { fclose(fp); fp=NULL; } }
  1726.                           XH_uninit;    // dΘsallocation mΘmoire & buffers
  1727.                           return 0;
  1728.                         }
  1729.                       } else {
  1730.                         if ( (opt.debug>0) && (opt.errlog!=NULL) ) {
  1731.                           fspc(opt.errlog,"warning"); fprintf(opt.errlog,"moving %s to an existing file %s"LF,liens[ptr]->fil,urlfil);
  1732.                           test_flush;
  1733.                         }
  1734.                       }
  1735.                       
  1736.                     }
  1737.                   }
  1738.                   
  1739.                   //printf("-> %s %s %s\n",liens[lien_tot-1]->adr,liens[lien_tot-1]->fil,liens[lien_tot-1]->sav);
  1740.                   
  1741.                   // note mΘtaphysique: il se peut qu'il y ait un index.html et un INDEX.HTML
  1742.                   // sous DOS ca marche pas trΦs bien... mais comme je suis gΘnial url_savename()
  1743.                   // est α mΩme de rΘgler ce problΦme
  1744.                 } else if (get_it==0) {    // adresse vraiment diffΘrente et potentiellement en html (pas de possibilitΘ de bouger la page tel quel α cause des <img src..> et cie)
  1745.                   rn=(char*) calloct(8192,1);
  1746.                   if (rn!=NULL) {
  1747.                     // On prΘpare une page qui sautera immΘdiatement sur la bonne URL
  1748.                     // Le scanner re-changera, ensuite, cette URL, pour la mirrorer!
  1749.                     strcpy(rn,"<HTML>"CRLF);
  1750.                     strcat(rn,"<!-- Created by HTTrack Website Copier/"HTTRACK_VERSION" "HTTRACK_AFF_AUTHORS" -->"CRLF);
  1751.                     strcat(rn,"<HEAD>"CRLF"<TITLE>Page has moved</TITLE>"CRLF"</HEAD>"CRLF"<BODY>"CRLF);
  1752.                     strcat(rn,"<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0; URL=");
  1753.                     strcat(rn,mov_url);    // URL
  1754.                     strcat(rn,"\">"CRLF);
  1755.                     strcat(rn,"<A HREF=\"");
  1756.                     strcat(rn,mov_url);
  1757.                     strcat(rn,"\">");
  1758.                     strcat(rn,"<B>Click here...</B></A>"CRLF);
  1759.                     strcat(rn,"</BODY>"CRLF);
  1760.                     strcat(rn,"<!-- Created by HTTrack Website Copier/"HTTRACK_VERSION" "HTTRACK_AFF_AUTHORS" -->"CRLF);
  1761.                     strcat(rn,"</HTML>"CRLF);
  1762.                     
  1763.                     // changer la page
  1764.                     if (r.adr) { freet(r.adr); r.adr=NULL; }
  1765.                     r.adr=rn;
  1766.                     r.size=strlen(r.adr);
  1767.                     strcpy(r.contenttype,"text/html");
  1768.                     if (opt.errlog) {
  1769.                       fspc(opt.errlog,"warning"); fprintf(opt.errlog,"File has moved from %s%s to %s"LF,urladr,urlfil,mov_url);
  1770.                       test_flush;
  1771.                     }
  1772.  
  1773.                     // dΘclarer page comme α Θcraser par le fichier si fichier binaire
  1774.                     // on va donc modifier la structure physique du site
  1775.                     // MAIS, en cas d'update, cela fonctionnera, car:
  1776.                     // 1. page moved: pas en cache (moved)
  1777.                     // 2. fichier qui Θcrase: mΩme en cas de get avec range:, comme c'est une erreur il 
  1778.                     // n'y aura pas de rΘponse "partial content"
  1779.                     /*
  1780.                     if (ishtml(mov_url)==0) {
  1781.                       if (!fexist(fconcat(opt.path_log,"moved.lst"))) {
  1782.                         FILE* fp=fopen(fconcat(opt.path_log,"moved.lst"),"wb");
  1783.                         if (fp) fclose(fp);
  1784.                       }
  1785.                       {
  1786.                         FILE* fp=fopen(fconcat(opt.path_log,"moved.lst"),"ab");
  1787.                         if (fp) {
  1788.                           fprintf(fp,"%s\n",mov_url);
  1789.                           fclose(fp);
  1790.                         }
  1791.                       }
  1792.                     }
  1793.                     */
  1794.  
  1795.                   }
  1796.                 }
  1797.               } else {
  1798.                 if (opt.errlog) {
  1799.                   fspc(opt.errlog,"error");
  1800.                   if (reponse==-2)
  1801.                     fprintf(opt.errlog,"Protocol ftp:// not supported for %s in file %s"LF,urladr,urlfil);
  1802.                   else
  1803.                     fprintf(opt.errlog,"Unrecoverable %s for %s%s (error move to %s)"LF,r.msg,urladr,urlfil,mov_url);
  1804.                   test_flush;
  1805.                 }
  1806.                 error=1;    // URL non reconnue
  1807.               }
  1808.             }
  1809. #if 0
  1810.             // i++;
  1811.             //} while((i<r.size) && (rn==NULL) && (error==0));
  1812. #endif
  1813.                       
  1814.           // erreur HTTP (ex: 404, not found)
  1815.         } else if (   (r.statuscode==412)
  1816.                    || (r.statuscode==416)
  1817.           ) {    // Precondition Failed, c'est α dire pour nous redemander TOUT le fichier
  1818.           if (fexist(liens[ptr]->sav)) {
  1819.             remove(liens[ptr]->sav);    // Eliminer
  1820.             if (!fexist(liens[ptr]->sav)) {  // Bien ΘliminΘ? (sinon on boucle..)
  1821. #if HDEBUG
  1822.               printf("Partial content NOT up-to-date, reget all file for %s\n",liens[ptr]->sav);
  1823. #endif
  1824.               if ( (opt.debug>1) && (opt.errlog!=NULL) ) {
  1825.                 //if (opt.errlog) {
  1826.                 fspc(opt.errlog,"debug"); fprintf(opt.errlog,"Partial file reget (%s) for %s%s"LF,r.msg,urladr,urlfil);
  1827.                 test_flush;
  1828.               }
  1829.               // enregistrer le MEME lien (MACRO)
  1830.               liens_record(liens[ptr]->adr,liens[ptr]->fil,liens[ptr]->sav,"","");
  1831.               if (liens[lien_tot]!=NULL) {    // OK, pas d'erreur
  1832.                 liens[lien_tot]->testmode=liens[ptr]->testmode;          // mode test?
  1833.                 liens[lien_tot]->link_import=0;       // pas mode import
  1834.                 liens[lien_tot]->depth=liens[ptr]->depth;
  1835.                 liens[lien_tot]->pass2=max(liens[ptr]->pass2,numero_passe);
  1836.                 liens[lien_tot]->retry=liens[ptr]->retry;
  1837.                 liens[lien_tot]->premier=liens[ptr]->premier;
  1838.                 liens[lien_tot]->precedent=ptr;
  1839.                 lien_tot++;
  1840.                 //
  1841.                 // canceller lien actuel
  1842.                 error=1;
  1843.                 strcpy(liens[ptr]->adr,"!");  // caractΦre bidon (invalide hash)
  1844. #if HTS_HASH
  1845. #else
  1846.                 liens[ptr]->sav_len=-1;       // taille invalide
  1847. #endif
  1848.                 //
  1849.               } else {  // oups erreur, plus de mΘmoire!!
  1850.                 printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  1851.                 if (opt.errlog) {
  1852.                   fprintf(opt.errlog,"Not enough memory, can not re-allocate %d bytes"LF,(add_tab_alloc+1)*sizeof(lien_url));
  1853.                   test_flush;
  1854.                 }
  1855.                 //if (opt.getmode & 1) { if (fp) { fclose(fp); fp=NULL; } }
  1856.                 XH_uninit;    // dΘsallocation mΘmoire & buffers
  1857.                 return 0;
  1858.               } 
  1859.             } else {
  1860.               if (opt.errlog!=NULL) {
  1861.                 fspc(opt.errlog,"error"); fprintf(opt.errlog,"Can not remove old file %s"LF,urlfil);
  1862.                 test_flush;
  1863.               }
  1864.             }
  1865.           } else {
  1866.             if (opt.errlog!=NULL) {
  1867.               fspc(opt.errlog,"warning"); fprintf(opt.errlog,"Unexpected 412/416 error (%s) for %s%s"LF,r.msg,urladr,urlfil);
  1868.               test_flush;
  1869.             }
  1870.           }
  1871.         } else if (r.statuscode!=200) {
  1872.           int can_retry=0;
  1873.  
  1874.           // cas o∙ l'on peut reessayer
  1875.           // -2=timeout -3=rateout (interne α httrack)
  1876.           switch(r.statuscode) {
  1877.           //case -1: can_retry=1; break;
  1878.           case -2: if (opt.hostcontrol) {    // timeout et retry ΘpuisΘs
  1879.             if ((opt.hostcontrol & 1) && (liens[ptr]->retry<=0)) {
  1880.               if ((opt.debug>1) && (opt.log!=NULL)) {
  1881.                 fspc(opt.log,"debug"); fprintf(opt.log,"Link banned: %s%s"LF,urladr,urlfil); test_flush;
  1882.               }
  1883.               host_ban(&opt,liens,ptr,lien_tot,back,back_max,filters,filter_max,&filptr,jump_identification(urladr));
  1884.               if ((opt.debug>1) && (opt.log!=NULL)) {
  1885.                 fspc(opt.log,"debug"); fprintf(opt.log,"Info: previous log - link banned: %s%s"LF,urladr,urlfil); test_flush;
  1886.               }
  1887.             } else can_retry=1;
  1888.                    } else can_retry=1;
  1889.             break;
  1890.           case -3: if ((opt.hostcontrol) && (liens[ptr]->retry<=0)) {    // too slow
  1891.             if (opt.hostcontrol & 2) {
  1892.               if ((opt.debug>1) && (opt.log!=NULL)) {
  1893.                 fspc(opt.log,"debug"); fprintf(opt.log,"Link banned: %s%s"LF,urladr,urlfil); test_flush;
  1894.               }
  1895.               host_ban(&opt,liens,ptr,lien_tot,back,back_max,filters,filter_max,&filptr,jump_identification(urladr));
  1896.               if ((opt.debug>1) && (opt.log!=NULL)) {
  1897.                 fspc(opt.log,"debug"); fprintf(opt.log,"Info: previous log - link banned: %s%s"LF,urladr,urlfil); test_flush;
  1898.               }
  1899.             } else can_retry=1;
  1900.                    } else can_retry=1;
  1901.             break;
  1902.           case -4:            // connect closed
  1903.             can_retry=1;
  1904.             break;
  1905.           case -5:            // other (non fatal) error
  1906.             can_retry=1;
  1907.             break;
  1908.           case 408: case 409: case 500: case 502: case 504: can_retry=1;
  1909.             break;
  1910.           }
  1911.           
  1912.           if ( strcmp(liens[ptr]->fil,"/primary") ) {    // pas primary (page 0)
  1913.             if ((liens[ptr]->retry<=0) || (!can_retry) ) {  // retry ΘpuisΘs (ou retry impossible)
  1914.               if (opt.errlog) {
  1915.                 if ((opt.retry>0) && (can_retry)){
  1916.                   fspc(opt.errlog,"error"); 
  1917.                   fprintf(opt.errlog,"\"%s\" (%d) after %d retries at link %s%s (from %s%s)"LF,r.msg,r.statuscode,opt.retry,urladr,urlfil,liens[liens[ptr]->precedent]->adr,liens[liens[ptr]->precedent]->fil);
  1918.                 } else {
  1919.                   if (r.statuscode==-10) {    // test OK
  1920.                     if ((opt.debug>0) && (opt.errlog!=NULL)) {
  1921.                       fspc(opt.errlog,"info"); 
  1922.                       fprintf(opt.errlog,"Test OK at link %s%s (from %s%s)"LF,urladr,urlfil,liens[liens[ptr]->precedent]->adr,liens[liens[ptr]->precedent]->fil);
  1923.                     }
  1924.                   } else {
  1925.                     if (strcmp(urlfil,"/robots.txt")) {       // ne pas afficher d'infos sur robots.txt par dΘfaut
  1926.                       fspc(opt.errlog,"error"); 
  1927.                       fprintf(opt.errlog,"\"%s\" (%d) at link %s%s (from %s%s)"LF,r.msg,r.statuscode,urladr,urlfil,liens[liens[ptr]->precedent]->adr,liens[liens[ptr]->precedent]->fil);
  1928.                     } else {
  1929.                       if (opt.debug>0) {  // on fera un alert si le retry Θchoue               
  1930.                         fspc(opt.errlog,"info"); fprintf(opt.errlog,"No robots.txt rules at %s"LF,urladr);
  1931.                         test_flush;
  1932.                       }
  1933.                     }
  1934.                   }
  1935.                 }
  1936.                 test_flush;
  1937.               }
  1938.               
  1939.               // ici on teste si on doit enregistrer la page tout de mΩme
  1940.               if (opt.errpage) {
  1941.                 // NO error in trop level
  1942.                 // due to the "no connection -> previous restored" hack
  1943.                 if (liens[ptr]->precedent != 0) {
  1944.                   store_errpage=1;
  1945.                 }
  1946.               }
  1947.               
  1948.             } else {    // retry!!
  1949.               if (opt.debug>0) {  // on fera un alert si le retry Θchoue               
  1950.                 fspc(opt.errlog,"warning"); fprintf(opt.errlog,"Retry after error %d (%s) at link %s%s (from %s%s)"LF,r.statuscode,r.msg,urladr,urlfil,liens[liens[ptr]->precedent]->adr,liens[liens[ptr]->precedent]->fil);
  1951.                 test_flush;
  1952.               }
  1953.               // redemander fichier
  1954.               liens_record(urladr,urlfil,savename,"","");
  1955.               if (liens[lien_tot]!=NULL) {    // OK, pas d'erreur
  1956.                 liens[lien_tot]->testmode=liens[ptr]->testmode;          // mode test?
  1957.                 liens[lien_tot]->link_import=0;       // pas mode import
  1958.                 liens[lien_tot]->depth=liens[ptr]->depth;
  1959.                 liens[lien_tot]->pass2=max(liens[ptr]->pass2,numero_passe);
  1960.                 liens[lien_tot]->retry=liens[ptr]->retry-1;    // moins 1 retry!
  1961.                 liens[lien_tot]->premier=liens[ptr]->premier;
  1962.                 liens[lien_tot]->precedent=liens[ptr]->precedent;
  1963.                 lien_tot++;
  1964.               } else {  // oups erreur, plus de mΘmoire!!
  1965.                 printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  1966.                 if (opt.errlog) {
  1967.                   fspc(opt.errlog,"panic"); 
  1968.                   fprintf(opt.errlog,"Not enough memory, can not re-allocate %d bytes"LF,(add_tab_alloc+1)*sizeof(lien_url));
  1969.                   test_flush;
  1970.                 }
  1971.                 //if (opt.getmode & 1) { if (fp) { fclose(fp); fp=NULL; } }
  1972.                 XH_uninit;    // dΘsallocation mΘmoire & buffers
  1973.                 return 0;
  1974.               } 
  1975.             }
  1976.           } else {
  1977.             if (opt.errlog) {
  1978.               fspc(opt.errlog,"info"); 
  1979.               fprintf(opt.errlog,"Info: no robots.txt at %s%s"LF,urladr,urlfil);
  1980.             }
  1981.           }
  1982.           if (!store_errpage) {
  1983.             if (r.adr) { freet(r.adr); r.adr=NULL; }  // dΘsalloc
  1984.             error=1;  // erreur!
  1985.           }
  1986.         }
  1987.         // FIN rattrapage des 301,302,307..
  1988.         // ------------------------------------------------------------
  1989.         
  1990.         
  1991.  
  1992.       }  // if !error
  1993.     }  // if !error
  1994.     
  1995.     if (!error) {  
  1996. #if DEBUG_SHOWTYPES
  1997.       if (strstr(REG,r.contenttype)==NULL) {
  1998.         strcat(REG,r.contenttype);
  1999.         strcat(REG,"\n");
  2000.         printf("%s\n",r.contenttype);
  2001.         io_flush;
  2002.       }
  2003. #endif
  2004.       
  2005.  
  2006.       // ------------------------------------------------------
  2007.       // ok, fichier chargΘ localement
  2008.       // ------------------------------------------------------
  2009.       
  2010.       // VΘrificateur d'intΘgritΘ
  2011.       #if DEBUG_CHECKINT
  2012.       {
  2013.         int i;
  2014.         for(i=0;i<back_max;i++) {
  2015.           char si[256];
  2016.           sprintf(si,"Test global aprΦs back_wait, index %d",i);
  2017.           _CHECKINT(&back[i],si)
  2018.         }
  2019.       }
  2020.       #endif
  2021.  
  2022.  
  2023.       /* info: updated */
  2024.       if (ptr>0) {
  2025.         // "mis α jour"
  2026.         if ((!r.notmodified) && (opt.is_update) && (!store_errpage)) {    // page modifiΘe
  2027.           if (strnotempty(savename)) {
  2028.             HTS_STAT.stat_updated_files++;
  2029.             if (opt.log!=NULL) {
  2030.               //if ((opt.debug>0) && (opt.log!=NULL)) {
  2031.               fspc(opt.log,"info"); fprintf(opt.log,"File updated: %s%s"LF,urladr,urlfil);
  2032.               test_flush;
  2033.             }
  2034.           }
  2035.         } else {
  2036.           if (!store_errpage) {
  2037.             if ( (opt.debug>0) && (opt.log!=NULL) ) {
  2038.               fspc(opt.log,"info"); fprintf(opt.log,"File recorded: %s%s"LF,urladr,urlfil);
  2039.               test_flush;
  2040.             }
  2041.           }
  2042.         }
  2043.       }
  2044.       
  2045.       // ------------------------------------------------------
  2046.       // traitement (parsing)
  2047.       // ------------------------------------------------------
  2048.  
  2049.       // traiter
  2050.       if (
  2051.            ( (is_hypertext_mime(r.contenttype))   /* Is HTML or Js, .. */
  2052.              || (may_be_hypertext_mime(r.contenttype) && (r.adr) )  /* Is real media, .. */
  2053.            )
  2054.         && (liens[ptr]->depth>0)            /* Depth > 0 (recurse depth) */
  2055.         && (r.adr!=NULL)        /* HTML Data exists */
  2056.         && (r.size>0)           /* And not empty */
  2057.         && (!store_errpage)     /* Not an html error page */
  2058.         && (savename[0]!='\0')  /* Output filename exists */
  2059.       ) {    // ne traiter que le html si autorisΘ
  2060.         // -- -- -- --
  2061.         // Parsing HTML
  2062.         if (!error) {
  2063.           // I'll have to segment this part
  2064. #include "htsparse.c"
  2065.         }
  2066.         // Fin parsing HTML
  2067.         // -- -- -- --
  2068.  
  2069.  
  2070.       }  // si text/html
  2071.       // -- -- --
  2072.       else {    // sauver fichier quelconque
  2073.         // -- -- --
  2074.         // sauver fichier
  2075.  
  2076.  
  2077.         /* En cas d'erreur, vΘrifier que fichier d'erreur existe */
  2078.         if (strnotempty(savename) == 0) {           // chemin de sauvegarde existant
  2079.           if (strcmp(urlfil,"/robots.txt")==0) {    // pas robots.txt
  2080.             if (store_errpage) {                    // c'est une page d'erreur
  2081.               int create_html_warning=0;
  2082.               int create_gif_warning=0;
  2083.               switch (ishtml(urlfil)) {      /* pas fichier html */
  2084.               case 0:                        /* non html */
  2085.                 {
  2086.                   char buff[256];
  2087.                   guess_httptype(buff,urlfil);
  2088.                   if (strcmp(buff,"image/gif")==0)
  2089.                     create_gif_warning=1;
  2090.                 }
  2091.                 break;
  2092.               case 1:                        /* html */
  2093.                 if (!r.adr) {
  2094.                 }
  2095.                 break;
  2096.               default:                       /* don't know.. */
  2097.                 break;    
  2098.               }
  2099.               /* CrΘer message d'erreur ? */
  2100.               if (create_html_warning) {
  2101.                 char* adr=(char*)malloc(strlen(HTS_DATA_ERROR_HTML)+1100);
  2102.                 if ( (opt.debug>0) && (opt.log!=NULL) ) {
  2103.                   fspc(opt.log,"info"); fprintf(opt.log,"Creating HTML warning file (%s)"LF,r.msg);
  2104.                   test_flush;
  2105.                 }
  2106.                 if (adr) {
  2107.                   if (r.adr) {
  2108.                     freet(r.adr);
  2109.                     r.adr=NULL;
  2110.                   }
  2111.                   sprintf(adr,HTS_DATA_ERROR_HTML,r.msg);
  2112.                   r.adr=adr;
  2113.                 }
  2114.               } else if (create_gif_warning) {
  2115.                 char* adr=(char*)malloc(HTS_DATA_UNKNOWN_GIF_LEN);
  2116.                 if ( (opt.debug>0) && (opt.log!=NULL) ) {
  2117.                   fspc(opt.log,"info"); fprintf(opt.log,"Creating GIF dummy file (%s)"LF,r.msg);
  2118.                   test_flush;
  2119.                 }
  2120.                 if (r.adr) {
  2121.                   freet(r.adr);
  2122.                   r.adr=NULL;
  2123.                 }
  2124.                 bcopy(HTS_DATA_UNKNOWN_GIF,adr,HTS_DATA_UNKNOWN_GIF_LEN);
  2125.                 r.adr=adr;
  2126.               }
  2127.             }
  2128.           }
  2129.         }
  2130.  
  2131.         if (strnotempty(savename) == 0) {    // pas de chemin de sauvegarde
  2132.           if (strcmp(urlfil,"/robots.txt")==0) {    // robots.txt
  2133.             if (r.adr) {
  2134.               int bptr=0;
  2135.               char line[256];
  2136.               char buff[8192];
  2137.               char infobuff[8192];
  2138.               int record=0;
  2139.               line[0]='\0'; buff[0]='\0'; infobuff[0]='\0';
  2140.               //
  2141. #if DEBUG_ROBOTS
  2142.               printf("robots.txt dump:\n%s\n",r.adr);
  2143. #endif
  2144.               do {
  2145.                 bptr+=binput(r.adr+bptr,line,200);
  2146.                 if (strfield(line,"user-agent:")) {
  2147.                   char* a;
  2148.                   a=line+11;
  2149.                   while(*a==' ') a++;    // sauter espace(s)
  2150.                   if (*a == '*') {
  2151.                     if (record != 2)
  2152.                       record=1;    // c pour nous
  2153.                   } else if (strfield(a,"httrack")) {
  2154.                     buff[0]='\0';      // re-enregistrer
  2155.                     infobuff[0]='\0';
  2156.                     record=2;          // locked
  2157. #if DEBUG_ROBOTS
  2158.                     printf("explicit disallow for httrack\n");
  2159. #endif
  2160.                   }
  2161.                   else record=0;
  2162.                 } else if (record) {
  2163.                   if (strfield(line,"disallow:")) {
  2164.                     char* a;
  2165.                     a=strchr(line,'#');
  2166.                     if (a) *a='\0';
  2167.                     while((line[strlen(line)-1]==' ') || (line[strlen(line)-1]==10) || (line[strlen(line)-1]==13))
  2168.                       line[strlen(line)-1]='\0';   // supprimer espaces
  2169.                     a=line+9;
  2170.                     while((*a==' ') || (*a==10) || (*a==13))
  2171.                       a++;    // sauter espace(s)
  2172.                     if (strnotempty(a)) {
  2173.                       if (strcmp(a,"/")) {      /* ignoring disallow: / */
  2174.                         strcat(buff,a);
  2175.                         strcat(buff,"\n");
  2176.                         if (strnotempty(infobuff)) strcat(infobuff,", ");
  2177.                         strcat(infobuff,a);
  2178.                       } else {
  2179.                         if (opt.errlog!=NULL) {
  2180.                           fspc(opt.errlog,"info"); fprintf(opt.errlog,"Note: %s robots.txt rules are too restrictive, ignoring /"LF,urladr);
  2181.                           test_flush;
  2182.                         }
  2183.                       }
  2184.                     }
  2185.                   }
  2186.                 }
  2187.               } while( (bptr<r.size) && (strlen(buff)<4096) );
  2188.               if (strnotempty(buff)) {
  2189.                 checkrobots_set(&robots,urladr,buff);
  2190.                 if (opt.log!=NULL) {
  2191.                   if (opt.log != opt.errlog) {
  2192.                     fspc(opt.log,"info"); fprintf(opt.log,"Note: robots.txt forbidden links for %s are: %s"LF,urladr,infobuff);
  2193.                     test_flush;
  2194.                   } 
  2195.                 }
  2196.                 if (opt.errlog!=NULL) {
  2197.                   fspc(opt.errlog,"info"); fprintf(opt.errlog,"Note: due to %s remote robots.txt rules, links begining with these path will be forbidden: %s (see in the options to disable this)"LF,urladr,infobuff);
  2198.                   test_flush;
  2199.                 }
  2200.               }
  2201.             }
  2202.           }
  2203.         } else if (r.is_write) {    // dΘja sauvΘ sur disque
  2204.           if (!ishttperror(r.statuscode))
  2205.             HTS_STAT.stat_files++;
  2206.           HTS_STAT.stat_bytes+=r.size;
  2207.           //printf("ok......\n");
  2208.         } else {
  2209.           // Si on doit sauver une page HTML sans la scanner, cela signifie que le niveau de
  2210.           // rΘcursion nous en empΩche
  2211.           // Dans ce cas on met un fichier indiquant ce fait
  2212.           // Si par la suite on doit retraiter ce fichier avec un niveau de rΘcursion plus
  2213.           // fort, on supprimera le readme, et on scannera le fichier html!
  2214.           // note: sautΘ si store_errpage (cαd si page d'erreur, non α scanner!)
  2215.           if ( (is_hypertext_mime(r.contenttype)) && (!store_errpage) && (r.size>0)) {  // c'est du html!!
  2216.             char tempo[HTS_URLMAXSIZE*2];
  2217.             FILE* fp;
  2218.             tempo[0]='\0';
  2219.             strcpy(tempo,savename);
  2220.             strcat(tempo,".readme");
  2221.             
  2222. #if HTS_DOSNAME
  2223.             // remplacer / par des slash arriΦre
  2224.             {
  2225.               int i=0;
  2226.               while(tempo[i]) {
  2227.                 if (tempo[i]=='/')
  2228.                   tempo[i]='\\';
  2229.                 i++;
  2230.               } 
  2231.             } 
  2232.             // a partir d'ici le slash devient antislash
  2233. #endif
  2234.             
  2235.             if ((fp=fopen(tempo,"wb"))!=NULL) {
  2236.               fprintf(fp,"Info-file generated by HTTrack Website Copier "HTTRACK_VERSION""CRLF""CRLF);
  2237.               fprintf(fp,"The file %s has not been scanned by HTS"CRLF,savename);
  2238.               fprintf(fp,"Some links contained in it may be unreachable locally."CRLF);
  2239.               fprintf(fp,"If you want to get these files, you have to set an upper recurse level, ");
  2240.               fprintf(fp,"and to rescan the URL."CRLF);
  2241.               fclose(fp);
  2242. #if HTS_WIN==0
  2243.               chmod(tempo,HTS_ACCESS_FILE);      
  2244. #endif
  2245.               usercommand(0,NULL,antislash(tempo));
  2246.             }
  2247.             
  2248.             
  2249.             if ( (opt.debug>0) && (opt.errlog!=NULL) ) {
  2250.               fspc(opt.errlog,"warning"); fprintf(opt.errlog,"Warning: store %s without scan: %s"LF,r.contenttype,savename);
  2251.               test_flush;
  2252.             }
  2253.           } else {
  2254.             if ((opt.getmode & 2)!=0) {    // ok autorisΘ
  2255.               if ( (opt.debug>1) && (opt.log!=NULL) ) {
  2256.                 fspc(opt.log,"debug"); fprintf(opt.log,"Store %s: %s"LF,r.contenttype,savename);
  2257.                 test_flush;
  2258.               }
  2259.             } else {    // lien non autorisΘ! (ex: cgi-bin en html)
  2260.               if ((opt.debug>1) && (opt.log!=NULL)) {
  2261.                 fspc(opt.log,"debug"); fprintf(opt.log,"non-html file ignored after upload at %s : %s"LF,urladr,urlfil);
  2262.                 test_flush;
  2263.               } 
  2264.               freet(r.adr); r.adr=NULL;
  2265.             }
  2266.           }
  2267.           
  2268.           //printf("extern=%s\n",r.contenttype);
  2269.  
  2270.           // ATTENTION C'EST ICI QU'ON SAUVE LE FICHIER!!          
  2271.           if (r.adr) {
  2272.             if (filesave(r.adr,(int)r.size,savename)!=0) {
  2273.               if (opt.errlog) {   
  2274.                 fspc(opt.errlog,"error"); fprintf(opt.errlog,"Unable to save file %s"LF,savename);
  2275.                 test_flush;
  2276.               }
  2277.             } else {
  2278.               if (!ishttperror(r.statuscode))
  2279.                 HTS_STAT.stat_files++;
  2280.               HTS_STAT.stat_bytes+=r.size;
  2281.             }
  2282.           }
  2283.           
  2284.         }
  2285.   
  2286.  
  2287.         /* Parsing of other media types (java, ram..) */
  2288.         /*
  2289.         if (strfield2(r.contenttype,"audio/x-pn-realaudio")) {
  2290.           if ((opt.debug>1) && (opt.log!=NULL)) {
  2291.             fspc(opt.log,"debug"); fprintf(opt.log,"(Real Media): parsing %s"LF,savename); test_flush;
  2292.           }
  2293.           if (fexist(savename)) {   // ok, existe bien!
  2294.             FILE* fp=fopen(savename,"r+b");
  2295.             if (fp) {
  2296.               if (!fseek(fp,0,SEEK_SET)) {
  2297.                 char line[HTS_URLMAXSIZE*2];
  2298.                 linput(fp,line,HTS_URLMAXSIZE);
  2299.                 if (strnotempty(line)) {
  2300.                   if ((opt.debug>1) && (opt.log!=NULL)) {
  2301.                     fspc(opt.log,"debug"); fprintf(opt.log,"(Real Media): detected %s"LF,line); test_flush;
  2302.                   }
  2303.                 }
  2304.               }
  2305.               fclose(fp);
  2306.             }
  2307.           }
  2308.         } else */
  2309.         if (opt.parsejava) {
  2310.           if (strlen(savename)>6) {  // fichier.class
  2311.             if (strfield(savename+strlen(savename)-6,".class")) {  // ok c'est une classe
  2312.               if (fexist(savename)) {   // ok, existe bien!
  2313.                 char err_msg[1100];
  2314.                 int r;
  2315.                 err_msg[0]='\0';
  2316.                 
  2317.                 //##char* buffer;
  2318.                 // JavaParsing f34R!
  2319.                 if ((opt.debug>1) && (opt.log!=NULL)) {
  2320.                   fspc(opt.log,"debug"); fprintf(opt.log,"(JavaClass catch file): parsing %s"LF,savename); test_flush;
  2321.                 }
  2322.                 
  2323.                 //##buffer=(char*) malloct(32768);
  2324.                 //##if (buffer) {
  2325.                 //
  2326.                 //##strcpy(buffer,"$BUFFER$");
  2327.                 //##hts_add_file(buffer);    // dΘclarer buffer
  2328.                 while(hts_add_file(NULL,-1) >= 0);   // clear chain
  2329.                 
  2330.                 r=hts_parse_java(savename,(char*) &err_msg);  // parsing
  2331.                 if (!r) {    // error
  2332.                   if (opt.errlog) {   
  2333.                     fprintf(opt.errlog,"Unable to parse java file %s : %s"LF,savename,err_msg);
  2334.                     test_flush;
  2335.                   }
  2336.                 } else {  // ok
  2337.                   char adr[HTS_URLMAXSIZE*2],fil[HTS_URLMAXSIZE*2],save[HTS_URLMAXSIZE*2];  // nom du fichier α sauver dans la boucle
  2338.                   char codebase[HTS_URLMAXSIZE*2];                  // codebase classe java
  2339.                   char lien[HTS_URLMAXSIZE*2];
  2340.                   //##char* a;
  2341.                   int file_position;
  2342.                   int pass_fix,prio_fix;
  2343.                   codebase[0]='\0';
  2344.                   //
  2345.                   
  2346.                   if ((opt.debug>1) && (opt.log!=NULL)) {
  2347.                     fspc(opt.log,"debug"); fprintf(opt.log,"(JavaClass catch file): parsing finished, now copying links.."LF); test_flush;
  2348.                   }
  2349.                   // recopie de "creer le lien"
  2350.                   //
  2351.                   
  2352.                   // adr = c'est la mΩme
  2353.                   // fil et save: save2 et fil2
  2354.                   prio_fix=maximum(liens[ptr]->depth-1,0);
  2355.                   pass_fix=max(liens[ptr]->pass2,numero_passe);
  2356.                   if (liens[ptr]->cod) strcpy(codebase,liens[ptr]->cod);       // codebase valable pour tt les classes descendantes
  2357.                   if (strnotempty(codebase)==0) {    // pas de codebase, construire
  2358.                     char* a;
  2359.                     strcpy(codebase,liens[ptr]->fil);
  2360.                     a=codebase+strlen(codebase)-1;
  2361.                     while((*a) && (*a!='/') && ((int) a > (int) codebase)) a--;
  2362.                     if (*a=='/')
  2363.                       *(a+1)='\0';    // couper
  2364.                   } else {    // couper http:// Θventuel
  2365.                     if (strfield(codebase,"http://")) {
  2366.                       char tempo[HTS_URLMAXSIZE*2];
  2367.                       char* a=codebase+7;
  2368.                       a=strchr(a,'/');    // aprΦs host
  2369.                       if (a) {  // ** msg erreur et vΘrifier?
  2370.                         strcpy(tempo,a);
  2371.                         strcpy(codebase,tempo);    // couper host
  2372.                       } else {
  2373.                         if (opt.errlog) {   
  2374.                           fprintf(opt.errlog,"Unexpected strstr error in base %s"LF,codebase);
  2375.                           test_flush;
  2376.                         }
  2377.                       }
  2378.                     }
  2379.                   }
  2380.                   //##a=buffer;
  2381.                   //##strcat(buffer,"&");  // fin du buffer
  2382.                   if (!((int) strlen(codebase)<HTS_URLMAXSIZE)) {    // trop long
  2383.                     if (opt.errlog) {   
  2384.                       fprintf(opt.errlog,"Codebase too long, parsing skipped (%s)"LF,codebase);
  2385.                       test_flush;
  2386.                     }
  2387.                     //##a=NULL;
  2388.                     while(hts_add_file(NULL,-1) >= 0);   // clear chain
  2389.                   }
  2390.                   while ( (file_position=hts_add_file(lien,-1)) >= 0 ) {
  2391.                     int dejafait=0;
  2392.                     /* //##
  2393.                     char* b;
  2394.                     
  2395.                      // prochain fichier α noter!
  2396.                      lien[0]='\0';
  2397.                      b=strchr(a,'&');  // marqueur de fin de chaine (voir hts_add_file)
  2398.                      if (b) {
  2399.                      if ( ( ((int) b-(int) a) + strlen(codebase)) < HTS_URLMAXSIZE)
  2400.                      strncat(lien,a,(int) b-(int) a);    // nom du fichier
  2401.                      else {
  2402.                      if (opt.errlog) {   
  2403.                      fprintf(opt.errlog,"Error: Java-Parser generated link that exceeds %d bytes"LF,HTS_URLMAXSIZE);
  2404.                      test_flush;
  2405.                      }
  2406.                      }
  2407.                      } else a=NULL;
  2408.                      
  2409.                       if (strnotempty(lien)==0) a=NULL;  // fin
  2410.                       if (a)
  2411.                       a=b+1;
  2412.                     */
  2413.                     
  2414.                     if (strnotempty(lien)) {
  2415.                       
  2416.                       // calculer les chemins et noms de sauvegarde
  2417.                       if (ident_url_relatif(lien,urladr,codebase,adr,fil)>=0) { // reformage selon chemin
  2418.                         int r;
  2419.                         
  2420.                         //  patcher opt pour garder structure originale!! (on ne patche pas les noms dans la classe java!)
  2421.                         //##if (!strstr(lien,"://")) {         // PAS tester les http://.. inutile (on ne va pas patcher le binaire :-( )
  2422.                         if (1) {
  2423.                           char tempo[HTS_URLMAXSIZE*2];
  2424.                           int a,b;
  2425.                           tempo[0]='\0';
  2426.                           a=opt.savename_type;
  2427.                           b=opt.savename_83;
  2428.                           opt.savename_type=0;
  2429.                           opt.savename_83=0;
  2430.                           // note: adr,fil peuvent Ωtre patchΘs
  2431.                           r=url_savename(adr,fil,save,NULL,NULL,NULL,NULL,&opt,liens,lien_tot,back,back_max,&cache,&hash,ptr,numero_passe);
  2432.                           opt.savename_type=a;
  2433.                           opt.savename_83=b;
  2434.                           if (r != -1) {
  2435.                             if (savename) {
  2436.                               if (lienrelatif(tempo,save,savename)==0) {
  2437.                                 if ((opt.debug>1) && (opt.log!=NULL)) {
  2438.                                   fspc(opt.log,"debug"); fprintf(opt.log,"(JavaClass catch file): relative link at %s build with %s and %s: %s"LF,adr,save,savename,tempo);
  2439.                                   test_flush;
  2440.                                 }
  2441.                                 //
  2442.                                 // xxc xxc xxc xxc TODO java:
  2443.                                 // rebuild the java class with patched strings...
  2444.                                 //
  2445.                                 if (strlen(tempo)<=strlen(lien)) {
  2446.                                   FILE* fp=fopen(savename,"r+b");
  2447.                                   if (fp) {
  2448.                                     if (!fseek(fp,file_position,SEEK_SET)) {
  2449.                                       //unsigned short int string_length=strlen(tempo);
  2450.                                       //fwrite(&valint,sizeof(string_length),1,fp);
  2451.                                       // xxc xxc ARGH! SI la taille est <, dΘcaler le code ?!
  2452.                                     } else {
  2453.                                       if (opt.log!=NULL) {
  2454.                                         fspc(opt.log,"debug"); fprintf(opt.log,"(JavaClass catch file): unable to patch: %s"LF,savename);
  2455.                                         test_flush;
  2456.                                       }
  2457.                                     }
  2458.                                     fclose(fp);
  2459.                                   } else {
  2460.                                     if (opt.log!=NULL) {
  2461.                                       fspc(opt.log,"debug"); fprintf(opt.log,"(JavaClass catch file): unable to open: %s"LF,savename);
  2462.                                       test_flush;
  2463.                                     }
  2464.                                   }
  2465.                                 } else {
  2466.                                   if (opt.log!=NULL) {
  2467.                                     fspc(opt.log,"debug"); fprintf(opt.log,"(JavaClass catch file): link too long, unable to write it: %s"LF,tempo);
  2468.                                     test_flush;
  2469.                                   }
  2470.                                 }
  2471.                               }
  2472.                             }
  2473.                           }
  2474.                         } else {
  2475.                           if ((opt.debug>1) && (opt.log!=NULL)) {
  2476.                             fspc(opt.log,"debug"); fprintf(opt.log,"(JavaClass catch file): file not caught: %s"LF,lien); test_flush;
  2477.                           }
  2478.                           r=-1;
  2479.                         }
  2480.                         //
  2481.                         if (r != -1) {
  2482.                           if ((opt.debug>1) && (opt.log!=NULL)) {
  2483.                             fspc(opt.log,"debug"); fprintf(opt.log,"(JavaClass catch file): %s%s -> %s (base %s)"LF,adr,fil,save,codebase); test_flush;
  2484.                           }
  2485.                           
  2486.                           // modifiΘ par rapport α l'autre version (cf prio_fix notamment et save2)
  2487.                           
  2488.                           // vΘrifier que le lien n'a pas dΘja ΘtΘ notΘ
  2489.                           // si c'est le cas, alors il faut s'assurer que la prioritΘ associΘe
  2490.                           // au fichier est la plus grande des deux prioritΘs
  2491.                           //
  2492.                           // On part de la fin et on essaye de se presser (Θconomise temps machine)
  2493. #if HTS_HASH
  2494.                           {
  2495.                             int i=hash_read(&hash,save,"",0);      // lecture type 0 (sav)
  2496.                             if (i>=0) {
  2497.                               liens[i]->depth=maximum(liens[i]->depth,prio_fix);
  2498.                               dejafait=1;
  2499.                             }
  2500.                           }
  2501. #else
  2502.                           {
  2503.                             register int l;
  2504.                             register int i;
  2505.                             l=strlen(save);
  2506.                             for(i=lien_tot-1;(i>=0) && (dejafait==0);i--) {
  2507.                               if (liens[i]->sav_len==l) {    // mΩme taille de chaεne
  2508.                                 if (strcmp(liens[i]->sav,save)==0) {    // existe dΘja
  2509.                                   liens[i]->depth=maximum(liens[i]->depth,prio_fix);
  2510.                                   dejafait=1;
  2511.                                 }
  2512.                               }
  2513.                             }
  2514.                           }
  2515. #endif
  2516.                           
  2517.                           
  2518.                           if (!dejafait) {
  2519.                             //
  2520.                             // >>>> CREER LE LIEN JAVA <<<<
  2521.                             
  2522.                             // enregistrer fichier de java (MACRO)
  2523.                             liens_record(adr,fil,save,"","");
  2524.                             if (liens[lien_tot]==NULL) {  // erreur, pas de place rΘservΘe
  2525.                               printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  2526.                               if (opt.errlog) { 
  2527.                                 fprintf(opt.errlog,"Not enough memory, can not re-allocate %d bytes"LF,(add_tab_alloc+1)*sizeof(lien_url));
  2528.                                 test_flush;
  2529.                               }
  2530.                               // if ((opt.getmode & 1) && (ptr>0)) { if (fp) { fclose(fp); fp=NULL; } }
  2531.                               XH_extuninit;    // dΘsallocation mΘmoire & buffers
  2532.                               return 0;
  2533.                             }  
  2534.                             
  2535.                             // mode test?                          
  2536.                             liens[lien_tot]->testmode=0;          // pas mode test
  2537.                             
  2538.                             liens[lien_tot]->link_import=0;       // pas mode import
  2539.                             
  2540.                             // Θcrire autres paramΦtres de la structure-lien
  2541.                             //if (meme_adresse)                                 
  2542.                             liens[lien_tot]->premier=liens[ptr]->premier;
  2543.                             //else    // sinon l'objet pΦre est le prΘcΘdent lui mΩme
  2544.                             //  liens[lien_tot]->premier=ptr;
  2545.                             
  2546.                             liens[lien_tot]->precedent=ptr;
  2547.                             // noter la prioritΘ
  2548.                             liens[lien_tot]->depth=prio_fix;
  2549.                             liens[lien_tot]->pass2=max(pass_fix,numero_passe);
  2550.                             liens[lien_tot]->retry=opt.retry;
  2551.                             
  2552.                             //strcpy(liens[lien_tot]->adr,adr);
  2553.                             //strcpy(liens[lien_tot]->fil,fil);
  2554.                             //strcpy(liens[lien_tot]->sav,save); 
  2555.                             if ((opt.debug>1) && (opt.log!=NULL)) {
  2556.                               fspc(opt.log,"debug"); fprintf(opt.log,"(JavaClass catch file): OK, NOTE: %s%s -> %s"LF,liens[lien_tot]->adr,liens[lien_tot]->fil,liens[lien_tot]->sav);
  2557.                               test_flush;
  2558.                             }
  2559.                             
  2560.                             lien_tot++;  // UN LIEN DE PLUS
  2561.                           }
  2562.                         }      
  2563.                         }  
  2564.                         
  2565.                       }  
  2566.                     }
  2567.                     
  2568.                   }
  2569.                   //##// effacer buffer temporaire
  2570.                   //##if (buffer) freet(buffer); buffer=NULL;
  2571.                   //##}  // if buffer
  2572.               }  // if exist
  2573.             }  // if .class
  2574.           }  // if strlen-savename
  2575.         }  // if opt.parsejava
  2576.         
  2577.         
  2578.         
  2579.       }  // text/html ou autre
  2580.       
  2581.     }  // if !error
  2582.     
  2583.  
  2584. jump_if_done:
  2585.     // libΘrer les liens
  2586.     if (r.adr) { freet(r.adr); r.adr=NULL; }   // libΘrer la mΘmoire!
  2587.     
  2588.     // prochain lien
  2589.     ptr++;
  2590.     
  2591.     // faut-il sauter le(s) lien(s) suivant(s)? (fichiers images α passer aprΦs les html)
  2592.     if (opt.getmode & 4) {    // sauver les non html aprΦs
  2593.       // sauter les fichiers selon la passe
  2594.       if (!numero_passe) {
  2595.         while((ptr<lien_tot)?(   liens[ptr]->pass2):0) ptr++;
  2596.       } else {
  2597.         while((ptr<lien_tot)?( ! liens[ptr]->pass2):0) ptr++;
  2598.       }
  2599.       if (ptr>=lien_tot) {     // fin de boucle
  2600.         if (!numero_passe) { // premiΦre boucle
  2601.           if ((opt.debug>1) && (opt.log!=NULL)) {
  2602.             fprintf(opt.log,LF"Now getting non-html files..."LF);
  2603.             test_flush;
  2604.           }
  2605.           numero_passe=1;   // seconde boucle
  2606.           ptr=0;
  2607.           // prochain pass2
  2608.           while((ptr<lien_tot)?(!liens[ptr]->pass2):0) ptr++;
  2609.           
  2610.           //printf("first link==%d\n");
  2611.           
  2612.         }
  2613.       }  
  2614.     }
  2615.         
  2616.     // a-t-on dΘpassΘ le quota?
  2617.     if ((opt.maxsite>0) && (HTS_STAT.stat_bytes>=opt.maxsite)) {
  2618.       if (opt.errlog) {
  2619.         fprintf(opt.errlog,"More than %d bytes have been transfered.. giving up"LF,opt.maxsite);
  2620.         test_flush;
  2621.       } 
  2622.       ptr=lien_tot;
  2623.     } else if ((opt.maxtime>0) && ((time_local()-HTS_STAT.stat_timestart)>opt.maxtime)) {            
  2624.       if (opt.errlog) {
  2625.         fprintf(opt.errlog,"More than %d seconds passed.. giving up"LF,opt.maxtime);
  2626.         test_flush;
  2627.       } 
  2628.       ptr=lien_tot;
  2629.     } else if (exit_xh) {  // sortir
  2630.       if (opt.errlog) {
  2631.         fspc(opt.errlog,"info"); fprintf(opt.errlog,"Exit requested by shell or user"LF);
  2632.         test_flush;
  2633.       } 
  2634.       ptr=lien_tot;
  2635.     }
  2636.   } while(ptr<lien_tot);
  2637.   //
  2638.   //
  2639.   //
  2640.  
  2641.  
  2642.   // no data transfered, no data saved
  2643.   // we assume that something was bad (no connection)
  2644.   // just backup old cache and restore everything
  2645.   if ( (HTS_STAT.stat_files == 0) && (new_stat_bytes < 2048) ) {
  2646.     if (opt.errlog) {
  2647.       fspc(opt.errlog,"info"); fprintf(opt.errlog,"No data seems to have been transfered during this session! : restoring previous one!"LF);
  2648.       test_flush;
  2649.     } 
  2650.     XH_uninit;
  2651.     if ( (fexist(fconcat(opt.path_log,"hts-cache/old.dat"))) && (fexist(fconcat(opt.path_log,"hts-cache/old.ndx"))) ) {
  2652.       remove(fconcat(opt.path_log,"hts-cache/new.dat"));
  2653.       remove(fconcat(opt.path_log,"hts-cache/new.ndx"));
  2654.       remove(fconcat(opt.path_log,"hts-cache/new.lst"));
  2655.       rename(fconcat(opt.path_log,"hts-cache/old.dat"),fconcat(opt.path_log,"hts-cache/new.dat"));
  2656.       rename(fconcat(opt.path_log,"hts-cache/old.ndx"),fconcat(opt.path_log,"hts-cache/new.ndx"));
  2657.       rename(fconcat(opt.path_log,"hts-cache/old.lst"),fconcat(opt.path_log,"hts-cache/new.lst"));
  2658.     }
  2659.     exit_xh=2;        /* interrupted (no connection detected) */
  2660.     return 1;
  2661.   }
  2662.  
  2663.  
  2664.   // purger!
  2665.   if (opt.delete_old) {
  2666.     if (cache.lst) {
  2667.       FILE *old_lst,*new_lst;
  2668.       //
  2669. #if HTS_ANALYSTE==2
  2670.       _hts_in_html_parsing=3;
  2671. #endif
  2672.       //
  2673.       fclose(cache.lst); cache.lst=NULL;
  2674.       old_lst=fopen(fconcat(opt.path_log,"hts-cache/old.lst"),"rb");
  2675.       if (old_lst) {
  2676.         LLint sz=fsize(fconcat(opt.path_log,"hts-cache/new.lst"));
  2677.         new_lst=fopen(fconcat(opt.path_log,"hts-cache/new.lst"),"rb");
  2678.         if ((new_lst) && (sz>0)) {
  2679.           char* adr=(char*) malloct((INTsys)sz);
  2680.           if (adr) {
  2681.             if ((int) fread(adr,1,(INTsys)sz,new_lst) == sz) {
  2682.               char line[1100];
  2683.               int purge=0;
  2684.               while(!feof(old_lst)) {
  2685.                 linput(old_lst,line,1000);
  2686.                 if (!strstr(adr,line)) {    // fichier non trouvΘ dans le nouveau?
  2687.                   char file[HTS_URLMAXSIZE*2];
  2688.                   strcpy(file,opt.path_html);
  2689.                   strcat(file,line+1);
  2690.                   file[strlen(file)-1]='\0';
  2691.                   if (fexist(file)) {       // toujours sur disque: virer
  2692.                     if (opt.log) {
  2693.                       fspc(opt.log,"info"); fprintf(opt.log,"Purging %s"LF,file);
  2694.                     }
  2695.                     remove(file); purge=1;
  2696.                   }
  2697.                 }
  2698.               }
  2699.               {
  2700.                 fseek(old_lst,0,SEEK_SET);
  2701.                 while(!feof(old_lst)) {
  2702.                   linput(old_lst,line,1000);
  2703.                   while(strnotempty(line) && (line[strlen(line)-1]!='/') && (line[strlen(line)-1]!='\\')) {
  2704.                     line[strlen(line)-1]='\0';
  2705.                   }
  2706.                   if (strnotempty(line))
  2707.                     line[strlen(line)-1]='\0';
  2708.                   if (strnotempty(line))
  2709.                     if (!strstr(adr,line)) {    // non trouvΘ?
  2710.                       char file[HTS_URLMAXSIZE*2];
  2711.                       strcpy(file,opt.path_html);
  2712.                       strcat(file,line+1);
  2713.                       while ((strnotempty(file)) && (rmdir(file)==0)) {    // ok, ΘliminΘ (existait)
  2714.                         purge=1;
  2715.                         if (opt.log) {
  2716.                           fspc(opt.log,"info"); fprintf(opt.log,"Purging directory %s/"LF,file);
  2717.                           while(strnotempty(file) && (file[strlen(file)-1]!='/') && (file[strlen(file)-1]!='\\')) {
  2718.                             file[strlen(file)-1]='\0';
  2719.                           }
  2720.                           if (strnotempty(file))
  2721.                             file[strlen(file)-1]='\0';
  2722.                         }
  2723.                       }
  2724.                     }
  2725.                 }
  2726.               }
  2727.               //
  2728.               if (!purge) {
  2729.                 if (opt.log) {
  2730.                   fprintf(opt.log,"No files purged"LF);
  2731.                 }
  2732.               }
  2733.             }
  2734.             freet(adr);
  2735.           }
  2736.           fclose(new_lst);
  2737.         }
  2738.         fclose(old_lst);
  2739.       }
  2740.       //
  2741. #if HTS_ANALYSTE==2
  2742.       _hts_in_html_parsing=0;
  2743. #endif
  2744.     }
  2745.   }
  2746.   // fin purge!
  2747.   
  2748.  
  2749.   // Indexation
  2750.   if (opt.kindex)
  2751.     index_finish(opt.path_html);
  2752.  
  2753.   // afficher rΘsumΘ dans log
  2754.   if (opt.log!=NULL) {
  2755.     int error   = fspc(NULL,"error");
  2756.     int warning = fspc(NULL,"warning");
  2757.     int info    = fspc(NULL,"info");
  2758.     char htstime[256];
  2759.     // int n=(int) (stat_loaded/(time_local()-HTS_STAT.stat_timestart));
  2760.     int n=(int) (new_stat_bytes/(time_local()-HTS_STAT.stat_timestart));
  2761.     sec2str(htstime,time_local()-HTS_STAT.stat_timestart);
  2762.     //fprintf(opt.log,LF"HTS-mirror complete in %s : %d links scanned, %d files written (%d bytes overall) [%d bytes received at %d bytes/sec]"LF,htstime,lien_tot-1,HTS_STAT.stat_files,stat_bytes,stat_loaded,n);
  2763.     fprintf(opt.log,LF"HTTrack mirror complete in %s : %d links scanned, %d files written (%d bytes overall) [%d bytes received at %d bytes/sec]"LF,htstime,(int)lien_tot-1,(int)HTS_STAT.stat_files,(int)HTS_STAT.stat_bytes,(int)new_stat_bytes,(int)n);
  2764.     if (error)
  2765.       fprintf(opt.log,"(%d errors, %d warnings, %d messages)"LF,error,warning,info);
  2766.     else
  2767.       fprintf(opt.log,"(No errors, %d warnings, %d messages)"LF,warning,info);
  2768.     test_flush;
  2769.   }
  2770. #if DEBUG_HASH
  2771.   // noter les collisions
  2772.   {
  2773.     int i;
  2774.     int empty1=0,empty2=0,empty3=0;
  2775.     for(i=0;i<HTS_HASH_SIZE;i++) {
  2776.       if (hash.hash[0][i] == -1)
  2777.         empty1++;
  2778.       if (hash.hash[1][i] == -1)
  2779.         empty2++;
  2780.       if (hash.hash[2][i] == -1)
  2781.         empty3++;
  2782.     }
  2783.     printf("\n");
  2784.     printf("Debug info: Hash-table report\n");
  2785.     printf("Number of files entered:   %d\n",hashnumber);
  2786.     printf("Table size:                %d\n",HTS_HASH_SIZE);
  2787.     printf("\n");
  2788.     printf("Longest chain sav:              %d, empty: %d\n",longest_hash[0],empty1);
  2789.     printf("Longest chain adr,fil:          %d, empty: %d\n",longest_hash[1],empty2);
  2790.     printf("Longest chain former_adr/fil:   %d, empty: %d\n",longest_hash[2],empty3);
  2791.     printf("\n");
  2792.   }
  2793. #endif    
  2794.   // fin afficher rΘsumΘ dans log
  2795.   
  2796.   // dΘsallocation mΘmoire & buffers  
  2797.   XH_uninit    
  2798.  
  2799.   return 1;    // OK
  2800. }
  2801. // version 2 pour le reste
  2802. // flusher si on doit lire peu α peu le fichier
  2803. #undef test_flush
  2804. #define test_flush if (opt->flush) { fflush(opt->log); fflush(opt->errlog); }
  2805.  
  2806.  
  2807. // Estimate transfer rate
  2808. int engine_stats() {
  2809.   if ( ((mtime_local() - HTS_STAT.imstat_timestart) >= 2000) && (new_stat_bytes>2048) ) {
  2810.     double cdif;
  2811.     double dif;
  2812.     cdif=mtime_local();
  2813.     dif=cdif - HTS_STAT.imstat_timestart;
  2814.     if (dif) {
  2815.       LLint byt=(int) (new_stat_bytes-HTS_STAT.istat_bytes);
  2816.       HTS_STAT.rate=(LLint)((double) ((double)byt/(dif/1000.0)));
  2817.       //
  2818.       HTS_STAT.istat_bytes=new_stat_bytes;
  2819.       HTS_STAT.imstat_timestart=cdif;
  2820.     }
  2821.     return 1;       /* refreshed */
  2822.   }
  2823.   return 0;
  2824. }
  2825.  
  2826.  
  2827. // bannir host (trop lent etc)
  2828. void host_ban(httrackp* opt,lien_url** liens,int ptr,int lien_tot,lien_back* back,int back_max,char** filters,int filter_max,int* filptr,char* host) {
  2829.   //register int l;
  2830.   register int i;
  2831.  
  2832.   if (host[0]=='!')
  2833.     return;    // erreur.. dΘja cancellΘ.. bizzard.. devrait pas arriver
  2834.  
  2835.   // interdire host
  2836.   if (*filptr < filter_max) {
  2837.     strcpy(filters[*filptr],"-");
  2838.     strcat(filters[*filptr],host);
  2839.     strcat(filters[*filptr],"/*");     // host/ * interdit
  2840.     (*filptr)++; *filptr=minimum(*filptr,filter_max);  
  2841.   }
  2842.   
  2843.   // oups
  2844.   if (strlen(host)<=1) {    // euhh?? longueur <= 1
  2845.     if (strcmp(host,"file://")) {
  2846.       //## if (host[0]!=lOCAL_CHAR) {  // pas local
  2847.       if (opt->log!=NULL) {
  2848.         fprintf(opt->log,"PANIC! HostCancel detected memory leaks [char %d]"LF,host[0]); test_flush;
  2849.       }          
  2850.       return;  // purΘe
  2851.     }
  2852.   }
  2853.   
  2854.   // couper connexion
  2855.   for(i=0;i<back_max;i++) {
  2856.     if (back[i].status>=0)    // rΘception OU prΩt
  2857.       if (strfield2(back[i].url_adr,host)) {
  2858. #if HTS_DEBUG_CLOSESOCK
  2859.         DEBUG_W("host control: deletehttp\n");
  2860. #endif
  2861.         back[i].status=0;  // terminΘ
  2862.         if (back[i].r.soc!=INVALID_SOCKET) deletehttp(&back[i].r);
  2863.         back[i].r.soc=INVALID_SOCKET;
  2864.         back[i].r.statuscode=-2;    // timeout (peu importe si c'est un traffic jam)
  2865.         strcpy(back[i].r.msg,"Link Cancelled by host control");
  2866.         
  2867.         if ((opt->debug>1) && (opt->log!=NULL)) {
  2868.           fprintf(opt->log,"Shutdown: %s%s"LF,back[i].url_adr,back[i].url_fil); test_flush;
  2869.         }          
  2870.       }
  2871.   }
  2872.   
  2873.   // effacer liens
  2874.   //l=strlen(host);
  2875.   for(i=0;i<lien_tot;i++) {
  2876.     //if (liens[i]->adr_len==l) {    // mΩme taille de chaεne
  2877.     // Calcul de taille sΘcurisΘe
  2878.     if (liens[i]) {
  2879.       if (liens[i]->adr) {
  2880.         int l = 0;
  2881.         while((liens[i]->adr[l]) && (l<1020)) l++;
  2882.         if ((l > 0) && (l<1020)) {   // sΘcuritΘ
  2883.           if (strfield2(jump_identification(liens[i]->adr),host)) {    // host
  2884.             if ((opt->debug>1) && (opt->log!=NULL)) {
  2885.               fprintf(opt->log,"Cancel: %s%s"LF,liens[i]->adr,liens[i]->fil); test_flush;
  2886.             }
  2887.             strcpy(liens[i]->adr,"!");    // cancel (invalide hash)
  2888. #if HTS_HASH
  2889. #else
  2890.             liens[i]->sav_len=-1;         // taille invalide
  2891. #endif
  2892.             // on efface pas le hash, because si on rencontre le lien, reverif sav..
  2893.           }
  2894.         } else {
  2895.           if (opt->log!=NULL) {
  2896.             char dmp[1040];
  2897.             dmp[0]='\0';
  2898.             strncat(dmp,liens[i]->adr,1024);
  2899.             fprintf(opt->log,"WARNING! HostCancel detected memory leaks [len %d at %d]"LF,l,i); test_flush;
  2900.             fprintf(opt->log,"dump 1024 bytes (address %d): "LF"%s"LF,(int)liens[i]->adr,dmp); test_flush;
  2901.           }          
  2902.         }
  2903.       } else {
  2904.         if (opt->log!=NULL) {
  2905.           fprintf(opt->log,"WARNING! HostCancel detected memory leaks [adr at %d]"LF,i); test_flush;
  2906.         }  
  2907.       }
  2908.     } else {
  2909.       if (opt->log!=NULL) {
  2910.         fprintf(opt->log,"WARNING! HostCancel detected memory leaks [null at %d]"LF,i); test_flush;
  2911.       }  
  2912.     }
  2913.     //}
  2914.   }
  2915. }
  2916.  
  2917.  
  2918.  
  2919.  
  2920.  
  2921.  
  2922. // vΘrifier prΘsence de l'arbo
  2923. int structcheck(char* s) {
  2924.   // vΘrifier la prΘsence des dossier(s)
  2925.   char *a=s;
  2926.   char nom[HTS_URLMAXSIZE*2];
  2927.   char *b;
  2928.  
  2929.   if (strnotempty(s)==0) return 0;
  2930.   if (strlen(s)>HTS_URLMAXSIZE) return 0;
  2931.  
  2932.   if (structcheck_buff==NULL) {
  2933.     structcheck_buff=(char*) malloct(65536);  // ** ** non dΘsallouΘ
  2934.     strcpy(structcheck_buff,"#");
  2935.   } else if (strlen(structcheck_buff)>65000) {
  2936.     strcpy(structcheck_buff,"#");  // rΘinit.. c'est idiot ** **
  2937.   }
  2938.   
  2939.   if (structcheck_buff) {
  2940.     b=nom;
  2941.     do {    
  2942.       if (*a) *b++=*a++;
  2943.       while((*a!='/') && (*a!='\0')) *b++=*a++;
  2944.       *b='\0';    // pas de ++ pour boucler
  2945.       if (*a=='/') {    // toujours dossier
  2946.         if (strnotempty(nom)) {
  2947.           char tempo[HTS_URLMAXSIZE*2];
  2948.           
  2949.           strcpy(tempo,"#"); strcat(tempo,nom); strcat(tempo,"#");
  2950.           if (strstr(structcheck_buff,tempo)==NULL) {    // non encore crΘΘ
  2951.             strcat(structcheck_buff,"#"); strcat(structcheck_buff,nom); strcat(structcheck_buff,"#");  // ajouter α la liste
  2952.                         
  2953. #if HTS_WIN
  2954.             if (mkdir(fconv(nom))!=0)
  2955. #else    
  2956.               if (mkdir(fconv(nom),HTS_ACCESS_FOLDER)!=0)
  2957. #endif
  2958.               {
  2959. #if HTS_REMOVE_ANNOYING_INDEX
  2960.                 // might be a filename with same name than this folder
  2961.                 // then, remove it to allow folder creation
  2962.                 // it happends when servers gives a folder index while
  2963.                 // requesting / page
  2964.                 // -> if the file can be opened (not a folder) then rename it
  2965.                 FILE* fp=fopen(fconv(nom),"ab");
  2966.                 if (fp) {
  2967.                   fclose(fp);
  2968.                   rename(fconv(nom),fconcat(fconv(nom),".txt"));
  2969.                 }
  2970.                 // if it fails, that's too bad
  2971. #if HTS_WIN
  2972.                 mkdir(fconv(nom));
  2973. #else    
  2974.                 mkdir(fconv(nom),HTS_ACCESS_FOLDER);
  2975. #endif
  2976. #endif
  2977.                 // Si existe dΘja renvoie une erreur.. tant pis
  2978.               }
  2979. #if HTS_WIN==0
  2980.               chmod(fconv(nom),HTS_ACCESS_FOLDER);
  2981. #endif
  2982.           }
  2983.         }
  2984.         *b++=*a++;    // slash
  2985.       } 
  2986.     } while(*a);
  2987.   }
  2988.   return 0;
  2989. }
  2990.  
  2991.  
  2992. // sauver un fichier
  2993. int filesave(char* adr,int len,char* s) {
  2994.   FILE* fp;
  2995.   // Θcrire le fichier
  2996.   if ((fp=filecreate(s))!=NULL) {
  2997.     int nl=0;
  2998.     if (len>0) {
  2999.       nl=(int) fwrite(adr,1,len,fp);
  3000.     }
  3001.     fclose(fp);
  3002.     usercommand(0,NULL,antislash(s));
  3003.     if (nl!=len)  // erreur
  3004.       return -1;
  3005.   } else
  3006.     return -1;
  3007.   
  3008.   return 0;
  3009. }
  3010.  
  3011.  
  3012. // ouvrir un fichier (avec chemin Un*x)
  3013. FILE* filecreate(char* s) {
  3014.   char fname[HTS_URLMAXSIZE*2];
  3015.   FILE* fp;
  3016.   fname[0]='\0';
  3017.  
  3018.   // noter lst
  3019.   filenote(s,NULL);
  3020.   
  3021.   // if (*s=='/') strcpy(fname,s+1); else strcpy(fname,s);    // pas de / (root!!) // ** SIIIIIII!!! α cause de -O <path>
  3022.   strcpy(fname,s);
  3023.  
  3024. #if HTS_DOSNAME
  3025.   // remplacer / par des slash arriΦre
  3026.   {
  3027.     int i=0;
  3028.     while(fname[i]) {
  3029.       if (fname[i]=='/')
  3030.         fname[i]='\\';
  3031.       i++;
  3032.     } 
  3033.   } 
  3034.   // a partir d'ici le slash devient antislash
  3035. #endif
  3036.   
  3037.   // construite le chemin si besoin est
  3038.   if (structcheck(s)!=0) {
  3039.     return NULL;
  3040.   }
  3041.   
  3042.   
  3043.   // ouvrir
  3044.   fp=fopen(fname,"wb");
  3045. #if HTS_WIN==0
  3046.   if (fp!=NULL) chmod(fname,HTS_ACCESS_FILE);
  3047. #endif
  3048.   return fp;
  3049. }
  3050.  
  3051. // noter fichier
  3052. int filenote(char* s,filecreate_params* params) {
  3053. //int filenote(char* s,char* params) {
  3054.   static FILE* lst = NULL;
  3055.   static char path[HTS_URLMAXSIZE*2]="";
  3056.   
  3057.   // gestion du fichier liste liste
  3058.   if (params) {
  3059.     //filecreate_params* p = (filecreate_params*) params;
  3060.     strcpy(path,params->path);
  3061.     lst=params->lst;
  3062.     return 0;
  3063.   } else if (lst) {
  3064.     char savelst[HTS_URLMAXSIZE*2];
  3065.     strcpy(savelst,fslash(s));
  3066.     // couper chemin?
  3067.     if (strnotempty(path)) {
  3068.       if (strncmp(fslash(path),savelst,strlen(path))==0) {  // couper
  3069.         strcpy(savelst,s+strlen(path));
  3070.       }
  3071.     }
  3072.     fprintf(lst,"[%s]"LF,savelst);
  3073.     fflush(lst);
  3074.   }
  3075.   return 1;
  3076. }
  3077.  
  3078. // executer commande utilisateur
  3079. HTS_INLINE void usercommand(int _exe,char* _cmd,char* file) {
  3080.   static int exe=0;
  3081.   static char cmd[2048]="";
  3082.   if (_exe) {
  3083.     strcpy(cmd,_cmd);
  3084.     if (strnotempty(cmd))
  3085.       exe=_exe;
  3086.     else
  3087.       exe=0;
  3088.   }
  3089.   if (exe) {
  3090.     if (strnotempty(file)) {
  3091.       if (strnotempty(cmd)) {
  3092.         usercommand_exe(cmd,file);
  3093.       }
  3094.     }
  3095.   }
  3096. }
  3097. void usercommand_exe(char* cmd,char* file) {
  3098.   char temp[8192];
  3099.   char c[2]="";
  3100.   int i;
  3101.   temp[0]='\0';
  3102.   //
  3103.   for(i=0;i<(int) strlen(cmd);i++) {
  3104.     if ((cmd[i]=='$') && (cmd[i+1]=='0')) {
  3105.       strcat(temp,file);
  3106.       i++;
  3107.     } else {
  3108.       c[0]=cmd[i]; c[1]='\0';
  3109.       strcat(temp,c);
  3110.     }
  3111.   }
  3112.   system(temp);
  3113. }
  3114.  
  3115. // Θcrire n espaces dans fp
  3116. HTS_INLINE int fspc(FILE* fp,char* type) {
  3117.   static int error=0,warning=0,info=0;
  3118.   //
  3119.   if (fp) {
  3120.     char s[256];
  3121.     time_t tt;
  3122.     struct tm* A;
  3123.     tt=time(NULL);
  3124.     A=localtime(&tt);
  3125.     strftime(s,250,"%H:%M:%S",A);
  3126.     if (strnotempty(type))
  3127.       fprintf(fp,"%s\t%c%s: \t",s,hichar(*type),type+1);
  3128.     else
  3129.       fprintf(fp,"%s\t \t",s);
  3130.     if (strcmp(type,"warning")==0)
  3131.       warning++;
  3132.     else if (strcmp(type,"error")==0)
  3133.       error++;
  3134.     else if (strcmp(type,"info")==0)
  3135.       info++;
  3136.   } 
  3137.   else if (!type)
  3138.     error=warning=info=0;     // reset
  3139.   else if (strcmp(type,"warning")==0)
  3140.     return warning;
  3141.   else if (strcmp(type,"error")==0)
  3142.     return error;
  3143.   else if (strcmp(type,"info")==0)
  3144.     return info;
  3145.   return 0;
  3146. }
  3147.  
  3148.  
  3149. // vΘrifier taux de transfert
  3150. void check_rate(double stat_timestart,int maxrate) {
  3151.   // vΘrifier taux de transfert (pas trop grand?)
  3152.   if (maxrate>0) {
  3153.     int r = (int) (new_stat_bytes/(time_local()-stat_timestart));    // taux actuel de transfert
  3154.     HTS_STAT.HTS_TOTAL_RECV_STATE=0;
  3155.     if (r>maxrate) {    // taux>taux autorisΘ
  3156.       int taux = (int) (((double) (r - maxrate) * 100) / (double) maxrate);
  3157.       if (taux<15)
  3158.         HTS_STAT.HTS_TOTAL_RECV_STATE=1;   // ralentir un peu (<15% dΘpassement)
  3159.       else if (taux<50)
  3160.         HTS_STAT.HTS_TOTAL_RECV_STATE=2;   // beaucoup (<50% dΘpassement)
  3161.       else
  3162.         HTS_STAT.HTS_TOTAL_RECV_STATE=3;   // ΘnormΘment (>50% dΘpassement)
  3163.     }
  3164.   }
  3165. }
  3166.  
  3167.  
  3168. // ---
  3169. // sous routines liΘes au moteur et au backing
  3170.  
  3171. // supplemental links ready (done) after ptr
  3172. int backlinks_done(lien_url** liens,int lien_tot,int ptr) {
  3173.   int n=0;
  3174.   int i;
  3175.   //Links done and stored in cache
  3176.   for(i=ptr+1;i<lien_tot;i++) {
  3177.     if (liens[i]) {
  3178.       if (liens[i]->pass2 == -1) {
  3179.         n++;
  3180.       }
  3181.     }
  3182.   }
  3183.   return n;
  3184. }
  3185.  
  3186. // remplir backing si moins de max_bytes en mΘmoire
  3187. HTS_INLINE int back_fillmax(lien_back* back,int back_max,httrackp* opt,cache_back* cache,lien_url** liens,int ptr,int numero_passe,int lien_tot) {
  3188.   if (back_incache(back,back_max)<opt->maxcache) {  // pas trop en mΘmoire?
  3189.     return back_fill(back,back_max,opt,cache,liens,ptr,numero_passe,lien_tot);
  3190.   }
  3191.   return -1;                /* plus de place */
  3192. }
  3193.  
  3194. // remplir backing
  3195. int back_fill(lien_back* back,int back_max,httrackp* opt,cache_back* cache,lien_url** liens,int ptr,int numero_passe,int lien_tot) {
  3196.   int n;
  3197.  
  3198.   // ajouter autant de socket qu'on peut ajouter
  3199.   n=opt->maxsoc-back_nsoc(back,back_max);
  3200.  
  3201.   // vΘrifier qu'il restera assez de place pour les tests ensuite (en thΘorie, 1 entrΘe libre restante suffirait)
  3202.   n=min( n, back_available(back,back_max) - 8 );
  3203.  
  3204.   // no space left on backing stack - do not back anymore
  3205.   if (back_stack_available(back,back_max) <= 2)
  3206.     n=0;
  3207.  
  3208.   if (n>0) {
  3209.     int p;
  3210.  
  3211.     if (ptr<cache->ptr_last) {      /* restart (2 scans: first html, then non html) */
  3212.       cache->ptr_ant=0;
  3213.     }
  3214.  
  3215.     p=ptr+1;
  3216.     /* on a dΘja parcouru */
  3217.     if (p<cache->ptr_ant)
  3218.       p=cache->ptr_ant;
  3219.     while( (p<lien_tot) && (n>0) ) {
  3220.     //while((p<lien_tot) && (n>0) && (p < ptr+opt->maxcache_anticipate)) {
  3221.       int ok=1;
  3222.       
  3223.       // on ne met pas le fichier en backing si il doit Ωtre traitΘ aprΦs
  3224.       if (liens[p]->pass2) {  // 2Φ passe
  3225.         if (numero_passe!=1)
  3226.           ok=0;
  3227.       } else {
  3228.         if (numero_passe!=0)
  3229.           ok=0;
  3230.       }
  3231.       
  3232.       // note: si un backing est fini, il reste en mΘmoire jusqu'α ce que
  3233.       // le ptr l'atteigne
  3234.       if (ok) {
  3235.         if (!back_exist(back,back_max,liens[p]->adr,liens[p]->fil,liens[p]->sav)) {
  3236.           if (back_add(back,back_max,opt,cache,liens[p]->adr,liens[p]->fil,liens[p]->sav,liens[liens[p]->precedent]->adr,liens[liens[p]->precedent]->fil,liens[p]->testmode,&liens[p]->pass2)==-1) {
  3237.             if ( (opt->debug>1) && (opt->errlog!=NULL) ) {
  3238.               fspc(opt->errlog,"debug"); fprintf(opt->errlog,"error: unable to add more links through back_add for back_fill"LF);
  3239.               test_flush;
  3240.             }                    
  3241. #if BDEBUG==1
  3242.             printf("error while adding\n");
  3243. #endif                  
  3244.             n=0;    // sortir
  3245.           } else {
  3246.             n--;
  3247. #if BDEBUG==1
  3248.             printf("backing: %s%s\n",liens[p]->adr,liens[p]->fil);          
  3249. #endif
  3250.           } 
  3251.         }
  3252.       }
  3253.       p++;
  3254.     }  // while
  3255.     /* sauver position derniΦre anticipation */
  3256.     cache->ptr_ant=p;
  3257.     cache->ptr_last=ptr;
  3258.   }
  3259.   return 0;
  3260. }
  3261. // ---
  3262.  
  3263.  
  3264.  
  3265.  
  3266.  
  3267.  
  3268.  
  3269.  
  3270.  
  3271.  
  3272.  
  3273.  
  3274.  
  3275.  
  3276.  
  3277.  
  3278.  
  3279.  
  3280. // routines de dΘtournement de SIGHUP & co (Unix)
  3281. void sig_finish( int code ) {       // finir et quitter
  3282.   signal(code,sig_term);  // quitter si encore
  3283.   exit_xh=1;
  3284.   printf("\nExit requested to engine (signal %d)\n",code);
  3285. }
  3286. void sig_term( int code ) {       // quitter brutalement
  3287.   printf("\nProgram terminated (signal %d)\n",code);
  3288.   exit(0);
  3289. }
  3290. #if HTS_WIN
  3291. void sig_ask( int code ) {        // demander
  3292.   static char s[256];
  3293.   signal(code,sig_term);  // quitter si encore
  3294.   printf("\nQuit program/Cancel? (Q/C) ");
  3295.   fflush(stdout);
  3296.   scanf("%s",s);
  3297.   if ( (s[0]=='y') || (s[0]=='Y') || (s[0]=='o') || (s[0]=='O') || (s[0]=='q') || (s[0]=='Q'))
  3298.     exit(0);     // quitter
  3299.   signal(code,sig_ask);  // remettre signal
  3300. }
  3301. #else
  3302. void sig_back( int code ) {       // ignorer et mettre en backing 
  3303.   signal(code,sig_ignore);
  3304.   sig_doback(0);
  3305. }
  3306. void sig_ask( int code ) {        // demander
  3307.   static char s[256];
  3308.   signal(code,sig_term);  // quitter si encore
  3309.   printf("\nQuit program/Background/bLind background/Cancel? (Q/B/L/C) ");
  3310.   fflush(stdout);
  3311.   scanf("%s",s);
  3312.   if ( (s[0]=='y') || (s[0]=='Y') || (s[0]=='o') || (s[0]=='O') || (s[0]=='q') || (s[0]=='Q'))
  3313.     exit(0);     // quitter
  3314.   else if ( (s[0]=='b') || (s[0]=='B') || (s[0]=='a') || (s[0]=='A') )
  3315.     sig_doback(0);  // arriΦre plan
  3316.   else if ( (s[0]=='l') || (s[0]=='L') )
  3317.     sig_doback(1);  // arriΦre plan
  3318.   else {
  3319.     printf("cancel..\n");
  3320.     signal(code,sig_ask);  // remettre signal
  3321.   }
  3322. }
  3323. void sig_ignore( int code ) {     // ignorer signal
  3324.   // // signal(code,sig_ignore);
  3325. }
  3326. void sig_doback(int blind) {       // mettre en backing 
  3327.   int out=-1;
  3328.   //
  3329.   printf("\nMoving to background to complete the mirror...\n"); fflush(stdout);
  3330.   if (!blind)
  3331.     out = open("hts-nohup.out",O_CREAT|O_WRONLY,S_IRUSR|S_IWUSR);
  3332.   if (out == -1)
  3333.     out = open("/dev/null",O_WRONLY,S_IRUSR|S_IWUSR);
  3334.   close(0);
  3335.   close(1);
  3336.   dup(out);
  3337.   close(2);
  3338.   dup(out);
  3339.   //
  3340.   switch (fork()) {
  3341.   case 0: 
  3342.     break;
  3343.   case -1:
  3344.     printf("Error: can not fork process\n");
  3345.     break;
  3346.   default:            // pere
  3347.     usleep(100000);   // pause 1/10s "A  microsecond  is  .000001s"
  3348.     _exit(0);
  3349.     break;  
  3350.   }
  3351. }
  3352. #endif
  3353. // fin routines de dΘtournement de SIGHUP & co
  3354.  
  3355. // Poll stdin.. si besoin
  3356. #if HTS_POLL
  3357. // lecture stdin des caractΦres disponibles
  3358. int read_stdin(char* s,int max) {
  3359.   int i=0;
  3360.   while((check_stdin()) && (i<(max-1)) )
  3361.     s[i++]=fgetc(stdin);
  3362.   s[i]='\0';
  3363.   return i;
  3364. }
  3365. #ifdef _WIN32
  3366. HTS_INLINE int check_stdin() {
  3367.   return (_kbhit());
  3368. }
  3369. #else
  3370. HTS_INLINE int check_flot(T_SOC s) {
  3371.   fd_set fds;
  3372.   struct timeval tv;
  3373.   FD_ZERO(&fds);
  3374.   FD_SET((T_SOC) s,&fds);
  3375.   tv.tv_sec=0;
  3376.   tv.tv_usec=0;
  3377.   select(s+1,&fds,NULL,NULL,&tv);
  3378.   return FD_ISSET(s,&fds);
  3379. }
  3380. HTS_INLINE int check_stdin() {
  3381.   fflush(stdout); fflush(stdin);
  3382.   if (check_flot(0))
  3383.     return 1;
  3384.   return 0;
  3385. }
  3386. #endif
  3387. #endif
  3388.  
  3389.  
  3390. // Attente de touche
  3391. #if HTS_ANALYSTE!=2
  3392. int ask_continue() {
  3393.   char s[12]="";
  3394.   printf("Press <Y><Enter> to confirm, <N><Enter> to abort\n");
  3395.   io_flush; linput(stdin,s,4);
  3396.   if (strnotempty(s)) {
  3397.     if ((strfield2(s,"N")) || (strfield2(s,"NO")) || (strfield2(s,"NON")))
  3398.       return 0;
  3399.   }
  3400.   return 1;
  3401. }
  3402. #else
  3403. int ask_continue() {
  3404.   char* s;
  3405.   s=hts_htmlcheck_query2(HTbuff);
  3406.   if (s) {
  3407.     if (strnotempty(s)) {
  3408.       if ((strfield2(s,"N")) || (strfield2(s,"NO")) || (strfield2(s,"NON")))
  3409.         return 0;
  3410.     }
  3411.     return 1;
  3412.   }
  3413.   return 1;
  3414. }
  3415. #endif
  3416.  
  3417. // nombre de digits dans un nombre
  3418. int nombre_digit(int n) {
  3419.   register int i=1;
  3420.   while(n >= 10) { n/=10; i++; }
  3421.   return i;
  3422. }
  3423.  
  3424.  
  3425. // renvoi adresse de la fin du token dans p
  3426. // renvoi NULL si la chaine est un token unique
  3427. // (PATCHE Θgalement la chaine)
  3428. // ex: "test" "test2" renvoi adresse sur espace
  3429. // flag==1 si chaine comporte des echappements comme \"
  3430. char* next_token(char* p,int flag) {
  3431.   int detect=0;
  3432.   int quote=0;
  3433.   p--;
  3434.   do {
  3435.     p++;
  3436.     if (flag && (*p=='\\')) {   // sauter \x ou \"
  3437.       if (quote) {
  3438.         char c='\0';
  3439.         if (*(p+1)=='\\')
  3440.           c='\\';
  3441.         else if (*(p+1)=='"')
  3442.           c='"';
  3443.         if (c) {
  3444.           char tempo[8192];
  3445.           tempo[0]=c; tempo[1]='\0';
  3446.           strcat(tempo,p+2);
  3447.           strcpy(p,tempo);
  3448.         }
  3449.       }
  3450.     }
  3451.     else if (*p==34) {  // guillemets (de fin)
  3452.       quote=!quote;
  3453.     }
  3454.     else if (*p==32) {
  3455.       if (!quote)
  3456.         detect=1;
  3457.     }
  3458.     else if (*p=='\0') {
  3459.       p=NULL;
  3460.       detect=1;
  3461.     }
  3462.   } while(!detect);
  3463.   return p;
  3464. }
  3465.  
  3466. // routines annexes 
  3467. #if HTS_ANALYSTE==2
  3468. // canceller un fichier (noter comme cancellable)
  3469. char* hts_cancel_file(char * s) {
  3470.   static char sav[HTS_URLMAXSIZE*2]="";
  3471.   if (s[0]!='\0')
  3472.   if (sav[0]=='\0')
  3473.     strcpy(sav,s);
  3474.   return sav;
  3475. }
  3476. void hts_cancel_test() {
  3477.   if (_hts_in_html_parsing==2)
  3478.     _hts_cancel=2;
  3479. }
  3480. void hts_cancel_parsing() {
  3481.   if (_hts_in_html_parsing)
  3482.    _hts_cancel=1;
  3483. }
  3484. #endif
  3485. //        for(_i=0;(_i<back_max) && (index<NFICH);_i++) {
  3486. //          i=(back_index+_i)%back_max;    // commencer par le "premier" (l'actuel)
  3487. //          if (back[i].status>=0) {     // signifie "lien actif"
  3488.  
  3489.  
  3490. /*  
  3491. hts_add_file, add/get elements in the add chain for java parsing
  3492. if file_position >= 0
  3493.   push 'file/file_position'
  3494.   return 1 (return 0 if exists)
  3495. else
  3496.   pop file -> 'file'
  3497.   return 'file_position'
  3498. else if empty/error
  3499.   return -1;
  3500. */
  3501. typedef struct addfile_chain {
  3502.   char name[1024];
  3503.   int pos;
  3504.   struct addfile_chain* next;
  3505. } addfile_chain;
  3506. int hts_add_file(char* file,int file_position) {
  3507.   static struct addfile_chain* chain=NULL;
  3508.  
  3509.   if (file_position>=0) {         /* copy file to the chain */
  3510.     struct addfile_chain** current;
  3511.     current=&chain;                     /* start from */
  3512.     while(*current) {
  3513.       if (strcmp((*current)->name,file)==0)
  3514.         return 0;                       /* already exists */
  3515.       current=&( (*current)->next );    /* 'next' address */
  3516.     }
  3517.     *current=calloc(1,sizeof(addfile_chain));
  3518.     if (*current) {
  3519.       (*current)->next=NULL;
  3520.       (*current)->pos=-1;
  3521.       (*current)->name[0]='\0';
  3522.     }
  3523.     if (*current) {
  3524.       strcpy((*current)->name,file);
  3525.       (*current)->pos=file_position;
  3526.       return 1;
  3527.     } else {
  3528.       printf("PANIC! Too many Java files during parsing [1]\n");
  3529.       return -1;
  3530.     }
  3531.   } else {                      /* copy last element in file and delete it */
  3532.     if (file)
  3533.       file[0]='\0';
  3534.     if (chain) {
  3535.       struct addfile_chain** current;
  3536.       int pos=-1;
  3537.       current=&chain;                     /* start from */
  3538.       while( (*current)->next ) {
  3539.         current=&( (*current)->next );    /* 'next' address */
  3540.       }
  3541.       if (file)
  3542.         strcpy(file,(*current)->name);
  3543.       pos=(*current)->pos;
  3544.       free(*current);
  3545.       *current=NULL;
  3546.       return pos;
  3547.     }
  3548.     return -1;                            /* no more elements */
  3549.   }
  3550.  
  3551.     /*
  3552.   static char* buffer;
  3553.   if (strlen(file)==8) {
  3554.     if (file[0]=='$') { // commande
  3555.       if (strcmp(file,"$BUFFER$")==0) {  // indiquer adresse buffer!
  3556.         buffer=file;    // le buffer
  3557.         buffer[0]='\0';
  3558.         return 1;
  3559.       }
  3560.     }
  3561.   }
  3562.   
  3563.   if (strlen(buffer)<32000) {   // vΘrifier..
  3564.     strcat(buffer,file);
  3565.     strcat(buffer,"&");  // sΘparateur
  3566.   } else {
  3567.     printf("PANIC! Too many Java files during parsing [1]\n");  // **
  3568.     buffer[32000]='\0';    // couper
  3569.   }
  3570.   */
  3571.  
  3572.   return 0;
  3573. }
  3574.  
  3575. #if HTS_ANALYSTE==2
  3576. // en train de parser un fichier html? rΘponse: % effectuΘs
  3577. // flag>0 : refresh demandΘ
  3578. int hts_is_parsing(int flag) {
  3579.   if (_hts_in_html_parsing) {  // parsing?
  3580.     if (flag>=0) _hts_in_html_poll=1;  // faudrait un tit refresh
  3581.     return max(_hts_in_html_done,1); // % effectuΘs
  3582.   } else {
  3583.     return 0;                 // non
  3584.   }
  3585. }
  3586. int hts_is_testing() {            // 0 non 1 test 2 purge
  3587.   if (_hts_in_html_parsing==2)
  3588.     return 1;
  3589.   else if (_hts_in_html_parsing==3)
  3590.     return 2;
  3591.   return 0;
  3592. }
  3593. // message d'erreur?
  3594. char* hts_errmsg() {
  3595.   return _hts_errmsg;
  3596. }
  3597. // mode pause transfer
  3598. int hts_setpause(int p) {
  3599.   if (p>=0) _hts_setpause=p;
  3600.   return _hts_setpause;
  3601. }
  3602. // rΘgler en cours de route les paramΦtres rΘglables..
  3603. // -1 : erreur
  3604. int hts_setopt(httrackp* opt) {
  3605.   if (opt) _hts_setopt=opt;
  3606.   return 0;
  3607. }
  3608. // ajout d'URL
  3609. // -1 : erreur
  3610. int hts_addurl(char** url) {
  3611.   if (url) _hts_addurl=url;
  3612.   return (_hts_addurl!=NULL);
  3613. }
  3614. int hts_resetaddurl() {
  3615.   _hts_addurl=NULL;
  3616.   return (_hts_addurl!=NULL);
  3617. }
  3618. // copier nouveaux paramΦtres si besoin
  3619. int copy_htsopt(httrackp* from,httrackp* to) {
  3620.   if (from->maxsite > -1) 
  3621.     to->maxsite = from->maxsite;
  3622.   
  3623.   if (from->maxfile_nonhtml > -1) 
  3624.     to->maxfile_nonhtml = from->maxfile_nonhtml;
  3625.   
  3626.   if (from->maxfile_html > -1) 
  3627.     to->maxfile_html = from->maxfile_html;
  3628.   
  3629.   if (from->maxsoc > 0) 
  3630.     to->maxsoc = from->maxsoc;
  3631.   
  3632.   if (from->nearlink > -1) 
  3633.     to->nearlink = from->nearlink;
  3634.   
  3635.   if (from->timeout > -1) 
  3636.     to->timeout = from->timeout;
  3637.   
  3638.   if (from->rateout > -1)
  3639.     to->rateout = from->rateout;
  3640.   
  3641.   if (from->maxtime > -1) 
  3642.     to->maxtime = from->maxtime;
  3643.   
  3644.   if (from->maxrate > -1)
  3645.     to->maxrate = from->maxrate;
  3646.   
  3647.   if (strnotempty(from->user_agent)) 
  3648.     strcpy(to->user_agent , from->user_agent);
  3649.   
  3650.   if (from->retry > -1) 
  3651.     to->retry = from->retry;
  3652.   
  3653.   if (from->hostcontrol > -1) 
  3654.     to->hostcontrol = from->hostcontrol;
  3655.   
  3656.   if (from->errpage > -1) 
  3657.     to->errpage = from->errpage;
  3658.  
  3659.   if (from->parseall > -1) 
  3660.     to->parseall = from->parseall;
  3661.  
  3662.  
  3663.   // test all: bit 8 de travel
  3664.   if (from->travel > -1)  {
  3665.     if (from->travel & 256)
  3666.       to->travel|=256;
  3667.     else
  3668.       to->travel&=255;
  3669.   }
  3670.  
  3671.  
  3672.   return 0;
  3673. }
  3674.  
  3675. #endif
  3676. //
  3677.  
  3678. // message copyright interne
  3679. void voidf(void) {
  3680.   char* a;
  3681.   a=""CRLF""CRLF;
  3682.   a="+-----------------------------------------------+"CRLF;
  3683.   a="|HyperTextTRACKer, Offline Browser Utility      |"CRLF;
  3684.   a="|                      HTTrack Website Copier   |"CRLF;
  3685.   a="|Code:         Windows Interface Xavier Roche   |"CRLF;
  3686.   a="|                    HTS/HTTrack Xavier Roche   |"CRLF;
  3687.   a="|                .class Parser Yann Philippot   |"CRLF;
  3688.   a="|                                               |"CRLF;
  3689.   a="|Tested on:                 Windows95,98,NT,2K  |"CRLF;
  3690.   a="|                           Linux PC            |"CRLF;
  3691.   a="|                           Sun-Solaris 5.6     |"CRLF;
  3692.   a="|                           AIX 4               |"CRLF;
  3693.   a="|                                               |"CRLF;
  3694.   a="|Copyright (C) Xavier Roche and other           |"CRLF;
  3695.   a="|contributors                                   |"CRLF;
  3696.   a="|                                               |"CRLF;
  3697.   a="|Use this program at your own risks!            |"CRLF;    
  3698.   a="+-----------------------------------------------+"CRLF;
  3699.   a=""CRLF;
  3700. }
  3701.  
  3702.  
  3703. // HTTrack Website Copier Copyright (C) Xavier Roche and other contributors
  3704. //
  3705.  
  3706.